@@ -1487,11 +1487,15 @@ void poly::divmod_univar (const poly &a, const poly &b, poly &q, poly &r, int va
14871487 * A heap element h is formatted as follows:
14881488 * - h[0] = index in a
14891489 * - h[1] = index in b
1490- * - h[2] = hash code ( -1 if no hash is used)
1490+ * - h[2] = -1 ( no hash is used)
14911491 * - h[3] = length of coefficient with sign
14921492 * - h[4...4+AN.poly_num_vars-1] = powers
14931493 * - h[4+AN.poly_num_vars...4+h[3]-1] = coefficient
14941494 *
1495+ * Note: the hashing trick as in multiplication cannot be used
1496+ * easily, since there is no tight upperbound on the exponents in
1497+ * the answer.
1498+ *
14951499 * For details, see M. Monagan, "Polynomial Division using Dynamic
14961500 * Array, Heaps, and Packed Exponent Vectors"
14971501 */
@@ -1533,42 +1537,7 @@ void poly::divmod_heap (const poly &a, const poly &b, poly &q, poly &r, bool onl
15331537 // allocate heap
15341538 int nb=b.number_of_terms ();
15351539
1536- // determine maximum power in variables
1537- WORD *maxpower = AT.WorkPointer ;
1538- AT.WorkPointer += AN.poly_num_vars ;
1539- WORD *maxpowera = AT.WorkPointer ;
1540- AT.WorkPointer += AN.poly_num_vars ;
1541- WORD *maxpowerb = AT.WorkPointer ;
1542- AT.WorkPointer += AN.poly_num_vars ;
1543-
1544- for (int i=0 ; i<AN.poly_num_vars ; i++)
1545- maxpowera[i] = maxpowerb[i] = 0 ;
1546-
1547- for (int ai=1 ; ai<a[0 ]; ai+=a[ai])
1548- for (int j=0 ; j<AN.poly_num_vars ; j++)
1549- maxpowera[j] = MaX (maxpowera[j], a[ai+1 +j]);
1550-
1551- for (int bi=1 ; bi<b[0 ]; bi+=b[bi])
1552- for (int j=0 ; j<AN.poly_num_vars ; j++)
1553- maxpowerb[j] = MaX (maxpowerb[j], b[bi+1 +j]);
1554-
1555- for (int i=0 ; i<AN.poly_num_vars ; i++)
1556- maxpower[i] = MaX (maxpowera[i],maxpowerb[i]);
1557-
1558- // if PROD(max.power) small, allocate hash table
1559- bool use_hash = true ;
1560- int nhash = 1 ;
1561-
1562- for (int i=0 ; i<AN.poly_num_vars ; i++) {
1563- if (nhash > POLY_MAX_HASH_SIZE / (maxpower[i]+1 )) {
1564- nhash = 1 ;
1565- use_hash = false ;
1566- break ;
1567- }
1568- nhash *= maxpower[i]+1 ;
1569- }
1570-
1571- WantAddPointers (nb+nhash);
1540+ WantAddPointers (nb);
15721541 WORD **heap = AT.pWorkSpace + AT.pWorkPointer ;
15731542
15741543 for (int i=0 ; i<nb; i++)
@@ -1579,10 +1548,6 @@ void poly::divmod_heap (const poly &a, const poly &b, poly &q, poly &r, bool onl
15791548 heap[0 ][2 ] = -1 ;
15801549 WCOPY (&heap[0 ][3 ], &a[1 ], a[1 ]);
15811550 heap[0 ][3 ] = a[a[1 ]];
1582-
1583- WORD **hash = AT.pWorkSpace + AT.pWorkPointer + nb;
1584- for (int i=0 ; i<nhash; i++)
1585- hash[i] = NULL ;
15861551
15871552 int qi=1 , ri=1 ;
15881553
@@ -1613,8 +1578,6 @@ void poly::divmod_heap (const poly &a, const poly &b, poly &q, poly &r, bool onl
16131578 pop_heap (BHEAD heap, nheap--);
16141579 p = heap[nheap];
16151580
1616- if (p[2 ]!=-1 ) hash[p[2 ]] = NULL ;
1617-
16181581 if (t[0 ] == -1 ) {
16191582 WCOPY (t, p, (5 +ABS (p[3 ])+AN.poly_num_vars ));
16201583 }
@@ -1650,97 +1613,55 @@ void poly::divmod_heap (const poly &a, const poly &b, poly &q, poly &r, bool onl
16501613 insert.pop_back ();
16511614 }
16521615
1653- // add elements to the heap
1654- while (true ) {
1655- // prepare the element
1656- if (p[1 ]==0 ) {
1657- p[0 ] += a[p[0 ]];
1658- if (p[0 ]==a[0 ]) break ;
1659- WCOPY (&p[3 ], &a[p[0 ]], a[p[0 ]]);
1660- p[3 ] = p[2 +p[3 ]];
1661- }
1662- else {
1663- if (!this_insert)
1664- p[1 ] += q[p[1 ]];
1665- this_insert = false ;
1666-
1667- if (p[1 ]==qi) { s++; break ; }
1668-
1669- for (int i=0 ; i<AN.poly_num_vars ; i++)
1670- p[4 +i] = b[p[0 ]+1 +i] + q[p[1 ]+1 +i];
1671-
1672- // if both polynomials are modulo p^1, use integer calculus
1673- if (both_mod_small) {
1674- p[4 +AN.poly_num_vars ] = ((LONG)b[p[0 ]+1 +AN.poly_num_vars ]*b[p[0 ]+b[p[0 ]]-1 ]*
1675- q[p[1 ]+1 +AN.poly_num_vars ]*q[p[1 ]+q[p[1 ]]-1 ]) % q.modp ;
1676- if (p[4 +AN.poly_num_vars ]==0 )
1677- p[3 ]=0 ;
1678- else {
1679- if (p[4 +AN.poly_num_vars ] > +q.modp /2 ) p[4 +AN.poly_num_vars ] -= q.modp ;
1680- if (p[4 +AN.poly_num_vars ] < -q.modp /2 ) p[4 +AN.poly_num_vars ] += q.modp ;
1681- p[3 ] = SGN (p[4 +AN.poly_num_vars ]);
1682- p[4 +AN.poly_num_vars ] = ABS (p[4 +AN.poly_num_vars ]);
1683- }
1684- }
1616+ // prepare the element to add to the heap
1617+ if (p[1 ]==0 ) {
1618+ p[0 ] += a[p[0 ]];
1619+ if (p[0 ]==a[0 ]) break ;
1620+ WCOPY (&p[3 ], &a[p[0 ]], a[p[0 ]]);
1621+ p[3 ] = p[2 +p[3 ]];
1622+ }
1623+ else {
1624+ if (!this_insert)
1625+ p[1 ] += q[p[1 ]];
1626+ this_insert = false ;
1627+
1628+ if (p[1 ]==qi) { s++; break ; }
1629+
1630+ for (int i=0 ; i<AN.poly_num_vars ; i++)
1631+ p[4 +i] = b[p[0 ]+1 +i] + q[p[1 ]+1 +i];
1632+
1633+ // if both polynomials are modulo p^1, use integer calculus
1634+ if (both_mod_small) {
1635+ p[4 +AN.poly_num_vars ] = ((LONG)b[p[0 ]+1 +AN.poly_num_vars ]*b[p[0 ]+b[p[0 ]]-1 ]*
1636+ q[p[1 ]+1 +AN.poly_num_vars ]*q[p[1 ]+q[p[1 ]]-1 ]) % q.modp ;
1637+ if (p[4 +AN.poly_num_vars ]==0 )
1638+ p[3 ]=0 ;
16851639 else {
1686- // otherwise, use form long calculus
1687- MulLong ((UWORD *)&b[p[0 ]+1 +AN.poly_num_vars ], b[p[0 ]+b[p[0 ]]-1 ],
1688- (UWORD *)&q[p[1 ]+1 +AN.poly_num_vars ], q[p[1 ]+q[p[1 ]]-1 ],
1689- (UWORD *)&p[4 +AN.poly_num_vars ], &p[3 ]);
1690- if (q.modp !=0 ) TakeNormalModulus ((UWORD *)&p[4 +AN.poly_num_vars ], &p[3 ],
1691- modq, nmodq, NOUNPACK);
1640+ if (p[4 +AN.poly_num_vars ] > +q.modp /2 ) p[4 +AN.poly_num_vars ] -= q.modp ;
1641+ if (p[4 +AN.poly_num_vars ] < -q.modp /2 ) p[4 +AN.poly_num_vars ] += q.modp ;
1642+ p[3 ] = SGN (p[4 +AN.poly_num_vars ]);
1643+ p[4 +AN.poly_num_vars ] = ABS (p[4 +AN.poly_num_vars ]);
16921644 }
1693-
1694- p[3 ] *= -1 ;
1695- }
1696-
1697- // with hashing, calculate hash value
1698- if (use_hash) {
1699- p[2 ] = 0 ;
1700- for (int i=0 ; i<AN.poly_num_vars ; i++)
1701- p[2 ] = (maxpower[i]+1 )*p[2 ] + p[4 +i];
17021645 }
17031646 else {
1704- p[2 ] = -1 ;
1647+ // otherwise, use form long calculus
1648+ MulLong ((UWORD *)&b[p[0 ]+1 +AN.poly_num_vars ], b[p[0 ]+b[p[0 ]]-1 ],
1649+ (UWORD *)&q[p[1 ]+1 +AN.poly_num_vars ], q[p[1 ]+q[p[1 ]]-1 ],
1650+ (UWORD *)&p[4 +AN.poly_num_vars ], &p[3 ]);
1651+ if (q.modp !=0 ) TakeNormalModulus ((UWORD *)&p[4 +AN.poly_num_vars ], &p[3 ],
1652+ modq, nmodq, NOUNPACK);
17051653 }
1706-
1707- // add it to a heap element if possible, otherwise push it
17081654
1709- if (!use_hash || (use_hash && hash[p[2 ]] == NULL )) {
1710- if (use_hash) hash[p[2 ]] = p;
1711- swap (heap[nheap],p);
1712- push_heap (BHEAD heap, ++nheap);
1713- break ;
1714- }
1715- else {
1716- WORD *h = hash[p[2 ]];
1717- // if both polynomials are modulo p^1, use integer calculus
1718- if (both_mod_small) {
1719- h[4 +AN.poly_num_vars ] = ((LONG)p[4 +AN.poly_num_vars ]*p[3 ] + h[4 +AN.poly_num_vars ]*h[3 ]) % q.modp ;
1720- if (h[4 +AN.poly_num_vars ]==0 )
1721- h[3 ]=0 ;
1722- else {
1723- if (h[4 +AN.poly_num_vars ] > +q.modp /2 ) h[4 +AN.poly_num_vars ] -= q.modp ;
1724- if (h[4 +AN.poly_num_vars ] < -q.modp /2 ) h[4 +AN.poly_num_vars ] += q.modp ;
1725- h[3 ] = SGN (h[4 +AN.poly_num_vars ]);
1726- h[4 +AN.poly_num_vars ] = ABS (h[4 +AN.poly_num_vars ]);
1727- }
1728- }
1729- else {
1730- // otherwise, use form long calculus
1731- AddLong ((UWORD *)&p[4 +AN.poly_num_vars ], p[3 ],
1732- (UWORD *)&h[4 +AN.poly_num_vars ], h[3 ],
1733- (UWORD *)&h[4 +AN.poly_num_vars ], &h[3 ]);
1734- if (q.modp !=0 ) TakeNormalModulus ((UWORD *)&h[4 +AN.poly_num_vars ], &h[3 ],
1735- modq, nmodq, NOUNPACK);
1736- }
1737-
1738- if (h[1 ]<p[1 ]) {
1739- swap (h[0 ],p[0 ]);
1740- swap (h[1 ],p[1 ]);
1741- }
1742- }
1655+ p[3 ] *= -1 ;
17431656 }
1657+
1658+ // no hashing
1659+ p[2 ] = -1 ;
1660+
1661+ // add it to a heap element if possible, otherwise push it
1662+
1663+ swap (heap[nheap],p);
1664+ push_heap (BHEAD heap, ++nheap);
17441665 }
17451666 while (t[0 ]==-1 || (nheap>0 && monomial_compare (BHEAD heap[0 ]+3 , t+3 )==0 ));
17461667
@@ -1826,7 +1747,6 @@ void poly::divmod_heap (const poly &a, const poly &b, poly &q, poly &r, bool onl
18261747 NumberFree (t," poly::div_heap" );
18271748
18281749 if (q.modp !=0 ) NumberFree (ltbinv," poly::div_heap" );
1829- AT.WorkPointer -= AN.poly_num_vars ;
18301750}
18311751
18321752/*
0 commit comments