/kernel/npolygon.cc

https://github.com/burcin/Singular · C++ · 675 lines · 408 code · 126 blank · 141 comment · 72 complexity · d534daccf4e4e6800820428c27e7e042 MD5 · raw file

  1. // ----------------------------------------------------------------------------
  2. // npolygon.cc
  3. // begin of file
  4. // Stephan Endrass, endrass@mathematik.uni-mainz.de
  5. // 23.7.99
  6. // ----------------------------------------------------------------------------
  7. #define NPOLYGON_CC
  8. #include <kernel/mod2.h>
  9. #ifdef HAVE_SPECTRUM
  10. #ifdef NPOLYGON_PRINT
  11. #include <iostream.h>
  12. #ifndef NPOLYGON_IOSTREAM
  13. #include <stdio.h>
  14. #endif
  15. #endif
  16. //#include <kernel/polys.h>
  17. #include <polys/monomials/p_polys.h>
  18. #include <polys/monomials/ring.h>
  19. #include <kernel/GMPrat.h>
  20. #include <kernel/kmatrix.h>
  21. #include <kernel/npolygon.h>
  22. #include <kernel/structs.h>
  23. // ----------------------------------------------------------------------------
  24. // Allocate memory for a linear form of k terms
  25. // ----------------------------------------------------------------------------
  26. void linearForm::copy_new( int k )
  27. {
  28. if( k > 0 )
  29. {
  30. c = new Rational[k];
  31. #ifndef NBDEBUG
  32. if( c == (Rational*)NULL )
  33. {
  34. #ifdef NPOLYGON_PRINT
  35. #ifdef NPOLYGON_IOSTREAM
  36. cerr <<
  37. "void linearForm::copy_new( int k ): no memory left ...\n" ;
  38. #else
  39. fprintf( stderr,
  40. "void linearForm::copy_new( int k ): no memory left ...\n");
  41. #endif
  42. #endif
  43. HALT();
  44. }
  45. #endif
  46. }
  47. else if( k == 0 )
  48. {
  49. c = (Rational*)NULL;
  50. }
  51. else if( k < 0 )
  52. {
  53. #ifdef NPOLYGON_PRINT
  54. #ifdef NPOLYGON_IOSTREAM
  55. cerr <<
  56. "void linearForm::copy_new( int k ): k < 0 ...\n";
  57. #else
  58. fprintf( stderr,
  59. "void linearForm::copy_new( int k ): k < 0 ...\n" );
  60. #endif
  61. #endif
  62. HALT();
  63. }
  64. }
  65. // ----------------------------------------------------------------------------
  66. // Delete the memory of a linear form
  67. // ----------------------------------------------------------------------------
  68. void linearForm::copy_delete( void )
  69. {
  70. if( c != (Rational*)NULL && N > 0 )
  71. delete [] c;
  72. copy_zero( );
  73. }
  74. // ----------------------------------------------------------------------------
  75. // Initialize deep from another linear form
  76. // ----------------------------------------------------------------------------
  77. void linearForm::copy_deep( const linearForm &l )
  78. {
  79. copy_new( l.N );
  80. for( int i=l.N-1; i>=0; i-- )
  81. {
  82. c[i] = l.c[i];
  83. }
  84. N = l.N;
  85. }
  86. // ----------------------------------------------------------------------------
  87. // Copy constructor
  88. // ----------------------------------------------------------------------------
  89. linearForm::linearForm( const linearForm &l )
  90. {
  91. copy_deep( l );
  92. }
  93. // ----------------------------------------------------------------------------
  94. // Destructor
  95. // ----------------------------------------------------------------------------
  96. linearForm::~linearForm( )
  97. {
  98. copy_delete( );
  99. }
  100. // ----------------------------------------------------------------------------
  101. // Define `=` to be a deep copy
  102. // ----------------------------------------------------------------------------
  103. linearForm & linearForm::operator = ( const linearForm &l )
  104. {
  105. copy_delete( );
  106. copy_deep( l );
  107. return *this;
  108. }
  109. // ----------------------------------------------------------------------------
  110. // ostream for linear form
  111. // ----------------------------------------------------------------------------
  112. #ifdef NPOLYGON_PRINT
  113. ostream & operator << ( ostream &s,const linearForm &l )
  114. {
  115. for( int i=0; i<l.N; i++ )
  116. {
  117. if( l.c[i] != (Rational)0 )
  118. {
  119. if( i > 0 && l.c[i] >= (Rational)0 )
  120. {
  121. #ifdef NPOLYGON_IOSTREAM
  122. s << "+";
  123. #else
  124. fprintf( stdout,"+" );
  125. #endif
  126. }
  127. s << l.c[i];
  128. #ifdef NPOLYGON_IOSTREAM
  129. s << "*x" << i+1;
  130. #else
  131. fprintf( stdout,"*x%d",i+1 );
  132. #endif
  133. }
  134. }
  135. return s;
  136. }
  137. #endif
  138. // ----------------------------------------------------------------------------
  139. // Equality of linear forms
  140. // ----------------------------------------------------------------------------
  141. int operator == ( const linearForm &l1,const linearForm &l2 )
  142. {
  143. if( l1.N!=l2.N )
  144. return FALSE;
  145. for( int i=l1.N-1; i >=0 ; i-- )
  146. {
  147. if( l1.c[i]!=l2.c[i] )
  148. return FALSE;
  149. }
  150. return TRUE;
  151. }
  152. // ----------------------------------------------------------------------------
  153. // Newton weight of a monomial
  154. // ----------------------------------------------------------------------------
  155. Rational linearForm::weight( poly m, const ring r ) const
  156. {
  157. Rational ret=(Rational)0;
  158. for( int i=0,j=1; i<N; i++,j++ )
  159. {
  160. ret += c[i]*(Rational)p_GetExp( m,j,r );
  161. }
  162. return ret;
  163. }
  164. // ----------------------------------------------------------------------------
  165. // Newton weight of a polynomial
  166. // ----------------------------------------------------------------------------
  167. Rational linearForm::pweight( poly m, const ring r ) const
  168. {
  169. if( m==(poly)NULL )
  170. return (Rational)0;
  171. Rational ret = weight( m, r );
  172. Rational tmp;
  173. for( m=pNext(m); m!=(poly)NULL; pIter(m) )
  174. {
  175. tmp = weight( m, r );
  176. if( tmp<ret )
  177. {
  178. ret = tmp;
  179. }
  180. }
  181. return ret;
  182. }
  183. // ----------------------------------------------------------------------------
  184. // Newton weight of a monomial shifted by the product of the variables
  185. // ----------------------------------------------------------------------------
  186. Rational linearForm::weight_shift( poly m, const ring r ) const
  187. {
  188. Rational ret=(Rational)0;
  189. for( int i=0,j=1; i<N; i++,j++ )
  190. {
  191. ret += c[i]*(Rational)( p_GetExp( m,j,r ) + 1 );
  192. }
  193. return ret;
  194. }
  195. // ----------------------------------------------------------------------------
  196. // Newton weight of a monomial (forgetting the first variable)
  197. // ----------------------------------------------------------------------------
  198. Rational linearForm::weight1( poly m, const ring r ) const
  199. {
  200. Rational ret=(Rational)0;
  201. for( int i=0,j=2; i<N; i++,j++ )
  202. {
  203. ret += c[i]*(Rational)p_GetExp( m,j,r );
  204. }
  205. return ret;
  206. }
  207. // ----------------------------------------------------------------------------
  208. // Newton weight of a monomial shifted by the product of the variables
  209. // (forgetting the first variable)
  210. // ----------------------------------------------------------------------------
  211. Rational linearForm::weight_shift1( poly m, const ring r ) const
  212. {
  213. Rational ret=(Rational)0;
  214. for( int i=0,j=2; i<N; i++,j++ )
  215. {
  216. ret += c[i]*(Rational)( p_GetExp( m,j,r ) + 1 );
  217. }
  218. return ret;
  219. }
  220. // ----------------------------------------------------------------------------
  221. // Test if all coefficients of a linear form are positive
  222. // ----------------------------------------------------------------------------
  223. int linearForm::positive( void )
  224. {
  225. for( int i=0; i<N; i++ )
  226. {
  227. if( c[i] <= (Rational)0 )
  228. {
  229. return FALSE;
  230. }
  231. }
  232. return TRUE;
  233. }
  234. // ----------------------------------------------------------------------------
  235. // Allocate memory for a newton polygon of k linear forms
  236. // ----------------------------------------------------------------------------
  237. void newtonPolygon::copy_new( int k )
  238. {
  239. if( k > 0 )
  240. {
  241. l = new linearForm[k];
  242. #ifndef NDEBUG
  243. if( l == (linearForm*)NULL )
  244. {
  245. #ifdef NPOLYGON_PRINT
  246. #ifdef NPOLYGON_IOSTREAM
  247. cerr <<
  248. "void newtonPolygon::copy_new( int k ): no memory left ...\n";
  249. #else
  250. fprintf( stderr,
  251. "void newtonPolygon::copy_new( int k ): no memory left ...\n" );
  252. #endif
  253. #endif
  254. HALT();
  255. }
  256. #endif
  257. }
  258. else if( k == 0 )
  259. {
  260. l = (linearForm*)NULL;
  261. }
  262. else if( k < 0 )
  263. {
  264. #ifdef NPOLYGON_PRINT
  265. #ifdef NPOLYGON_IOSTREAM
  266. cerr << "void newtonPolygon::copy_new( int k ): k < 0 ...\n";
  267. #else
  268. fprintf( stderr,
  269. "void newtonPolygon::copy_new( int k ): k < 0 ...\n" );
  270. #endif
  271. #endif
  272. HALT();
  273. }
  274. }
  275. // ----------------------------------------------------------------------------
  276. // Delete the memory of a Newton polygon
  277. // ----------------------------------------------------------------------------
  278. void newtonPolygon::copy_delete( void )
  279. {
  280. if( l != (linearForm*)NULL && N > 0 )
  281. delete [] l;
  282. copy_zero( );
  283. }
  284. // ----------------------------------------------------------------------------
  285. // Initialize deep from another Newton polygon
  286. // ----------------------------------------------------------------------------
  287. void newtonPolygon::copy_deep( const newtonPolygon &np )
  288. {
  289. copy_new( np.N );
  290. for( int i=0; i<np.N; i++ )
  291. {
  292. l[i] = np.l[i];
  293. }
  294. N = np.N;
  295. }
  296. // ----------------------------------------------------------------------------
  297. // Copy constructor
  298. // ----------------------------------------------------------------------------
  299. newtonPolygon::newtonPolygon( const newtonPolygon &np )
  300. {
  301. copy_deep( np );
  302. }
  303. // ----------------------------------------------------------------------------
  304. // Destructor
  305. // ----------------------------------------------------------------------------
  306. newtonPolygon::~newtonPolygon( )
  307. {
  308. copy_delete( );
  309. }
  310. // ----------------------------------------------------------------------------
  311. // We define `=` to be a deep copy
  312. // ----------------------------------------------------------------------------
  313. newtonPolygon & newtonPolygon::operator = ( const newtonPolygon &np )
  314. {
  315. copy_delete( );
  316. copy_deep( np );
  317. return *this;
  318. }
  319. // ----------------------------------------------------------------------------
  320. // Initialize a Newton polygon from a polynomial
  321. // ----------------------------------------------------------------------------
  322. newtonPolygon::newtonPolygon( poly f, const ring s )
  323. {
  324. copy_zero( );
  325. int *r=new int[s->N];
  326. poly *m=new poly[s->N];
  327. KMatrix<Rational> mat(s->N,s->N+1 );
  328. int i,j,stop=FALSE;
  329. linearForm sol;
  330. // ---------------
  331. // init counters
  332. // ---------------
  333. for( i=0; i<s->N; i++ )
  334. {
  335. r[i] = i;
  336. }
  337. m[0] = f;
  338. for( i=1; i<s->N; i++ )
  339. {
  340. m[i] = pNext(m[i-1]);
  341. }
  342. // -----------------------------
  343. // find faces (= linear forms)
  344. // -----------------------------
  345. do
  346. {
  347. // ---------------------------------------------------
  348. // test if monomials p.m[r[0]]m,...,p.m[r[p.vars-1]]
  349. // are linearely independent
  350. // ---------------------------------------------------
  351. for( i=0; i<s->N; i++ )
  352. {
  353. for( j=0; j<s->N; j++ )
  354. {
  355. // mat.set( i,j,pGetExp( m[r[i]],j+1 ) );
  356. mat.set( i,j,p_GetExp( m[i],j+1,s ) );
  357. }
  358. mat.set( i,j,1 );
  359. }
  360. if( mat.solve( &(sol.c),&(sol.N) ) == s->N )
  361. {
  362. // ---------------------------------
  363. // check if linearForm is positive
  364. // check if linearForm is extremal
  365. // ---------------------------------
  366. if( sol.positive( ) && sol.pweight( f,s ) >= (Rational)1 )
  367. {
  368. // ----------------------------------
  369. // this is a face or the polyhedron
  370. // ----------------------------------
  371. add_linearForm( sol );
  372. sol.c = (Rational*)NULL;
  373. sol.N = 0;
  374. }
  375. }
  376. // --------------------
  377. // increment counters
  378. // --------------------
  379. for( i=1; r[i-1] + 1 == r[i] && i < s->N; i++ );
  380. for( j=0; j<i-1; j++ )
  381. {
  382. r[j]=j;
  383. }
  384. if( i>1 )
  385. {
  386. m[0]=f;
  387. for( j=1; j<i-1; j++ )
  388. {
  389. m[j]=pNext(m[j-1]);
  390. }
  391. }
  392. r[i-1]++;
  393. m[i-1]=pNext(m[i-1]);
  394. if( m[s->N-1] == (poly)NULL )
  395. {
  396. stop = TRUE;
  397. }
  398. } while( stop == FALSE );
  399. }
  400. #ifdef NPOLYGON_PRINT
  401. ostream & operator << ( ostream &s,const newtonPolygon &a )
  402. {
  403. #ifdef NPOLYGON_IOSTREAM
  404. s << "Newton polygon:" << endl;
  405. #else
  406. fprintf( stdout,"Newton polygon:\n" );
  407. #endif
  408. for( int i=0; i<a.N; i++ )
  409. {
  410. s << a.l[i];
  411. #ifdef NPOLYGON_IOSTREAM
  412. s << endl;
  413. #else
  414. fprintf( stdout,"\n" );
  415. #endif
  416. }
  417. return s;
  418. }
  419. #endif
  420. // ----------------------------------------------------------------------------
  421. // Add a face to the newton polygon
  422. // ----------------------------------------------------------------------------
  423. void newtonPolygon::add_linearForm( const linearForm &l0 )
  424. {
  425. int i;
  426. newtonPolygon np;
  427. // -------------------------------------
  428. // test if linear form is already here
  429. // -------------------------------------
  430. for( i=0; i<N; i++ )
  431. {
  432. if( l0==l[i] )
  433. {
  434. return;
  435. }
  436. }
  437. np.copy_new( N+1 );
  438. np.N = N+1;
  439. for( i=0; i<N; i++ )
  440. {
  441. np.l[i].copy_shallow( l[i] );
  442. l[i].copy_zero( );
  443. }
  444. np.l[N] = l0;
  445. copy_delete( );
  446. copy_shallow( np );
  447. np.copy_zero( );
  448. return;
  449. }
  450. // ----------------------------------------------------------------------------
  451. // Newton weight of a monomial
  452. // ----------------------------------------------------------------------------
  453. Rational newtonPolygon::weight( poly m, const ring r ) const
  454. {
  455. Rational ret = l[0].weight( m,r );
  456. Rational tmp;
  457. for( int i=1; i<N; i++ )
  458. {
  459. tmp = l[i].weight( m,r );
  460. if( tmp < ret )
  461. {
  462. ret = tmp;
  463. }
  464. }
  465. return ret;
  466. }
  467. // ----------------------------------------------------------------------------
  468. // Newton weight of a monomial shifted by the product of the variables
  469. // ----------------------------------------------------------------------------
  470. Rational newtonPolygon::weight_shift( poly m, const ring r ) const
  471. {
  472. Rational ret = l[0].weight_shift( m, r );
  473. Rational tmp;
  474. for( int i=1; i<N; i++ )
  475. {
  476. tmp = l[i].weight_shift( m, r );
  477. if( tmp < ret )
  478. {
  479. ret = tmp;
  480. }
  481. }
  482. return ret;
  483. }
  484. // ----------------------------------------------------------------------------
  485. // Newton weight of a monomial (forgetting the first variable)
  486. // ----------------------------------------------------------------------------
  487. Rational newtonPolygon::weight1( poly m, const ring r ) const
  488. {
  489. Rational ret = l[0].weight1( m, r );
  490. Rational tmp;
  491. for( int i=1; i<N; i++ )
  492. {
  493. tmp = l[i].weight1( m, r );
  494. if( tmp < ret )
  495. {
  496. ret = tmp;
  497. }
  498. }
  499. return ret;
  500. }
  501. // ----------------------------------------------------------------------------
  502. // Newton weight of a monomial shifted by the product of the variables
  503. // (forgetting the first variable)
  504. // ----------------------------------------------------------------------------
  505. Rational newtonPolygon::weight_shift1( poly m, const ring r ) const
  506. {
  507. Rational ret = l[0].weight_shift1( m, r );
  508. Rational tmp;
  509. for( int i=1; i<N; i++ )
  510. {
  511. tmp = l[i].weight_shift1( m, r );
  512. if( tmp < ret )
  513. {
  514. ret = tmp;
  515. }
  516. }
  517. return ret;
  518. }
  519. /*
  520. // ----------------------------------------------------------------------------
  521. // Chcek if the polynomial belonging to the Newton polygon
  522. // is semiquasihomogeneous (sqh)
  523. // ----------------------------------------------------------------------------
  524. int newtonPolygon::is_sqh( void ) const
  525. {
  526. return ( N==1 ? TRUE : FALSE );
  527. }
  528. // ----------------------------------------------------------------------------
  529. // If the polynomial belonging to the Newton polygon is sqh,
  530. // return its weights vector
  531. // ----------------------------------------------------------------------------
  532. Rational* newtonPolygon::sqh_weights( void ) const
  533. {
  534. return ( N==1 ? l[0].c : (Rational*)NULL );
  535. }
  536. int newtonPolygon::sqh_N( void ) const
  537. {
  538. return ( N==1 ? l[0].N : 0 );
  539. }
  540. */
  541. #endif /* HAVE_SPECTRUM */
  542. // ----------------------------------------------------------------------------
  543. // npolygon.cc
  544. // end of file
  545. // ----------------------------------------------------------------------------