Macaulay2 / Macaulay2/M2

Weyl algebra division by zero error in characteristic $p>0$.

Open
#4,082 2 comments 0 reactions 0 assignees View on GitHub
Engine WeylAlgebras
Dominant language
Macaulay2
Stars
435
Forks
297
Avg merge
4d 20h
Merged PRs (30d)
11

Description

In reducing polynomials to standard form in the Weyl algebra, the commutation rule $d x = x d + 1$ is applied. This ultimately leads to computation of binomial coefficients in the coefficient ring. In positive characteristic this fails in the kernel:
```
A = ZZ/5[x, d, WeylAlgebra => { x => d}]
d^20*x^10
```
resulting in
```
stdio:2:4:(3): error: division by zero
```

Suggested fix (courtesy of GPT 5.2 and @antonleykin): the culprit seems to be buried in the binomial function in
https://github.com/Macaulay2/M2/blob/54c4a8356d5f49337ff898a9cf66c3930ae6b304/M2/Macaulay2/e/weylalg.cpp#L227-L246

Suggested fix using https://en.wikipedia.org/wiki/Lucas%27s_theorem:

```
ring_elem WeylAlgebra::binomial(int top, int bottom) const
{
// Assumption: 0 <= bottom <= top.
if (bottom == 0) return K_->from_long(1);
if (bottom == 1) return K_->from_long(top);

const int p = K_->characteristic(); // (or however the coeff ring exposes it)

// In char p, avoid division by 0 when bottom >= p
if (p > 0 && bottom >= p)
{
ring_elem result = K_->from_long(1);

int n = top;
int k = bottom;

while (k > 0)
{
int ni = n % p;
int ki = k % p;

if (ki > ni)
{
K_->remove(result);
return K_->from_long(0);
}

// Safe: 0 <= ki <= ni < p, so denominators 1..(p-1) never hit 0
ring_elem term = binomial(ni, ki); // this call will *not* re-enter Lucas
ring_elem tmp = K_->mult(result, term);

K_->remove(result);
K_->remove(term);
result = tmp;

n /= p;
k /= p;
}
return result;
}

// existing code path (works in char 0, and in char p when bottom < p)
if (top <= binomtop) return K_->from_long(binomtable[top][bottom]);
ring_elem result = K_->from_long(1);
for (int a = 0; a < bottom; a++)
{
ring_elem b = K_->from_long(top - a);
ring_elem result1 = K_->mult(result, b);
K_->remove(result);
K_->remove(b);
ring_elem c = K_->from_long(a + 1);
result = K_->divide(result1, c); // exact in char 0; safe in char p if bottom < p
K_->remove(c);
}
return result;
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the characteristic-5 Weyl algebra command from the issue, then inspect M2/Macaulay2/e/weylalg.cpp around lines 227–246, especially WeylAlgebra::binomial. Compare the existing division path with the proposed Lucas-theorem approach. Done means the command reduces successfully without a division-by-zero error in positive characteristic.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.