Macaulay2 / Macaulay2/M2

discriminant returns the unnormalized resultant, so it differs from the discriminant by (-1)^(n(n-1)/2) and by the leading coefficient, and the docs state no convention

Open
#4,619 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bugs directory under discussion
Dominant language
Macaulay2
Stars
435
Forks
297
Avg merge
4d 20h
Merged PRs (30d)
11

Description

This issue was triaged from [`bugs/mike/0-discriminant`](https://github.com/Macaulay2/M2/blob/388c1ff0ce30d83751dea7bc7eac77fdc1305dd7/bugs/mike/0-discriminant), one of the 857 files removed from the pre-GitHub `bugs/` tree by [`d2c8d27826`](https://github.com/Macaulay2/M2/commit/d2c8d27826) and catalogued in [#36](https://github.com/Macaulay2/M2/issues/36). **The commentary below was written by Claude (Claude Opus 5, via Claude Code)**, not by @d-torrance, whose account posted it -- please weigh it accordingly.

### The original file, verbatim

```text
QQ[a, b, c, x]
((a-b))^2 + discriminant((x-a)*(x-b),x)
((a-b)*(a-c)*(b-c))^2 + discriminant((x-a)*(x-b)*(x-c),x)
discriminant(x^2+b*x+c, x)

end
-- Is the sign right?

i10 : QQ[a, b, c, x]

o10 = QQ[a, b, c, x]

o10 : PolynomialRing

i11 : ((a-b))^2 + discriminant((x-a)*(x-b),x)

o11 = 0

o11 : QQ[a, b, c, x]

i12 : ((a-b)*(a-c)*(b-c))^2 + discriminant((x-a)*(x-b)*(x-c),x)

o12 = 0

o12 : QQ[a, b, c, x]

i22 : discriminant(x^2+b*x+c, x)

2
o22 = - b + 4c

o22 : QQ[a, b, c, x]
```

### Where it stands today

`discriminant(f, x)` returns the resultant of `f` and `f'` without either of the normalizations that
turn a resultant into a discriminant, and the documentation does not say so. The standard definition is

$$\operatorname{disc}(f) \;=\; \frac{(-1)^{n(n-1)/2}}{a_n}\,\operatorname{Res}(f, f')$$

for $f$ of degree $n$ with leading coefficient $a_n$. M2 returns $\operatorname{Res}(f, f')$:

```m2
i1 : R = QQ[a,b,c,x]

o1 = R

o1 : PolynomialRing

i2 : discriminant(x^2+b*x+c, x)

2
o2 = - b + 4c

o2 : R

i3 : discriminant(a*x^2+b*x+c, x)

2 2
o3 = - a*b + 4a c

o3 : R
```

`o2` is the negative of the familiar $b^2-4c$, and `o3` is $-a\,(b^2-4ac)$ — off by the sign and by the
leading coefficient.

The sign discrepancy follows $(-1)^{n(n-1)/2}$ exactly, so it appears at some degrees and not others.
Against the product-of-differences formula:

| degree | exponent $n(n-1)/2$ | expected factor | M2 |
| --- | --- | --- | --- |
| 2 | 1 | $-1$ | `disc((x-a)(x-b))` $= -(a-b)^2$ |
| 3 | 3 | $-1$ | `disc((x-a)(x-b)(x-c))` $= -\prod^2$ |
| 4 | 6 | $+1$ | `disc` of the quartic $= +\prod^2$, agrees |

Degree 4 agreeing is what rules out a plain sign error and points at the missing factor.

### Cause

The implementation is a single line, with no normalization applied:

https://github.com/Macaulay2/M2/blob/development/M2/Macaulay2/packages/Elimination.m2#L127-L128

### The documentation does not disambiguate

The doc node gives the output only as *"the discriminant of `f` with respect to `x`"*:

https://github.com/Macaulay2/M2/blob/development/M2/Macaulay2/packages/Elimination.m2#L214-L234

and its own example is a quadratic, so the rendered page displays the sign-flipped value with nothing
to explain it. A reader has no way to tell which convention is in force.

### Two ways to resolve, and they are not equivalent

Recorded without a recommendation, since the trade-off belongs to whoever owns this code:

* **Document the convention.** Cheapest, breaks nothing. `resultant(f, f')` is a legitimate quantity
and callers have depended on this output for a long time.
* **Normalize the output.** Makes `discriminant` return the discriminant, and would change results for
every existing caller — including at degrees where nothing looks wrong today, since the leading
coefficient factor applies at every degree.

Not the same as [#4449](https://github.com/Macaulay2/M2/issues/4449), which is `discriminant` raising
`expected nonzero polynomials` when `diff(x,f)` vanishes identically in characteristic $p$.

Worth flagging for whoever picks this up: [#4472](https://github.com/Macaulay2/M2/pull/4472) is open
against that issue and rewrites this same line, adding an early `if diff(f,x) == 0 then return 0`
guard around the `resultant` call. It does not change the normalization, so the two are independent —
but they touch the same two lines and would want coordinating.

### Where this came from

Cataloguing the `bugs/` directory removed in d2c8d27826 (#36). `bugs/mike/0-discriminant` records the
degree 2 and 3 identities above and asks simply: *"Is the sign right?"*

`open` · disposition `issue` · source of truth: [`bug-triage/catalog.tsv`](https://github.com/d-torrance/M2/blob/bug-triage/bug-triage/catalog.tsv)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the implementation at M2/Macaulay2/packages/Elimination.m2#L127-L128 and the documentation node around lines 214-234, then review #4472 because it changes the same lines. The issue is complete only after the convention is decided and either documented or normalized, with corresponding behavior checks.

Written by the indexing model from the issue text.

Assessment

Domain
documentation, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.