Skip to content

[feature](function) Support gamma scalar function - #68029

Open
RH211-sys wants to merge 3 commits into
apache:masterfrom
RH211-sys:feat-gamma-function
Open

RH211-sys wants to merge 3 commits into
apache:masterfrom
RH211-sys:feat-gamma-function

Conversation

@RH211-sys

@RH211-sys RH211-sys commented Sep 15, 2026

Copy link
Copy Markdown

What problem does this PR solve?

Related issue: #48203

Related PR: #51576, #60111 — earlier attempts at the same function, both closed without merging.

Problem Summary:

Add the gamma scalar function, which generalizes the factorial to real numbers: gamma(n) is
(n - 1)! for a positive integer n, and gamma(0.5) is sqrt(pi).

  • BE: gamma is registered in be/src/exprs/function/math.cpp on top of std::tgamma. The poles
    are mapped to NULL instead of the value the C library returns: gamma(0) (including -0.0) and
    every negative integer return NULL, and so does negative infinity, which the BE classifies as a
    negative integer pole. A NaN argument returns NaN. Positive infinity, and any argument whose value
    overflows a double (171.5 is still finite, 171.8 and 172 are Infinity), return Infinity, and
    so does a very small positive argument, where gamma(a) is about 1 / a. This follows the
    convention of the other math functions here: a domain error such as sqrt(-1) or ln(0) is NULL
    and only overflow is Infinity.
  • FE: Gamma (unary, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral), the
    Nereids visitor entry, and the builtin scalar function registration. The FE does not compute
    gamma itself. An earlier revision folded gamma(<literal>) through commons-math3, but that
    library and std::tgamma classify the boundaries differently — gamma(-1000.5) is NaN from
    commons-math3 and -0.0 from the BE, gamma(-150.5) is 0.0 against -4.4784476581511713e-264,
    and gamma(10) differs by about 11 ulp — so the folding was removed instead of trying to keep the
    two in step. gamma feeds neither partition nor bucket pruning, so the folding had no benefit, and
    the BE is now the single implementation.
  • Tests: a regression suite (test_gamma.groovy) covering the domain — the poles, -0.0, negative
    non-integers, ±infinity, NaN, the overflow onset, subnormal inputs, and large negative arguments
    that underflow to a signed zero — plus a BE unit test and a GammaTest FE unit test for the new FE
    statements. The suite evaluates gamma(<literal>), gamma of a table column, and both folding
    switches, so every evaluation path is covered.

Release note

Add the gamma scalar function. gamma(n) is (n - 1)! for a positive integer n; gamma(0)
and the negative integers return NULL.

Check List (For Author)

  • Test
    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
  • Behavior changed:
    • Yes: gamma(<literal>) is not constant folded in the FE any more, it is computed by the BE
      like every other invocation. The values returned to the client are unchanged.
    • No.
  • Does this need documentation?

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

Manual test:

  • select gamma(5), gamma(0.5), gamma(-1.5), gamma(0), gamma(-1), gamma(-3); returns
    24.000000000000004, 1.772453850905516, 2.3632718012073544, NULL, NULL, NULL; the same values
    come back with set debug_skip_fold_constant=true and with
    set enable_fold_constant_by_be=true, i.e. every evaluation path agrees.
  • Boundary values: gamma(cast('nan' as double)) is NaN, gamma(cast('inf' as double)) is Infinity,
    gamma(cast('-inf' as double)) is NULL, gamma(cast('-0.0' as double)) is NULL, gamma(171) is
    7.257415615308056E306, gamma(171.5) is 9.483367566824735E307, gamma(171.8) is Infinity,
    gamma(1e-300) is 9.999999999999763E299, gamma(5e-324) is Infinity, and gamma(-1000.5) is
    -0.0.
  • explain select gamma(v) from t where gamma(v) > 10; still plans an olap scan with the predicate
    and the projection applied.

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

### What problem does this PR solve?

Related issue: [apache#48203](apache#48203)

Problem Summary:

Add the `gamma` scalar function, which generalizes the factorial to real numbers: `gamma(n)` is
`(n - 1)!` for a positive integer `n`, and `gamma(0.5)` is `sqrt(pi)`.

- BE: `gamma` is registered in `be/src/exprs/function/math.cpp` on top of `std::tgamma`. The poles
  are mapped to NULL instead of the value the C library produces: `gamma(0)` and every negative
  integer return NULL, and so does negative infinity, which the BE classifies as a negative
  integer pole. A NaN argument returns NaN, and positive infinity or an argument large enough to
  overflow a double (`gamma(172)` and above) returns Infinity.
- FE: `Gamma` (unary, `ExplicitlyCastableSignature`, `AlwaysNullable`, `PropagateNullLiteral`),
  the Nereids visitor entry, and the builtin scalar function registration.
- FE constant folding: `NumericArithmetic.gamma`, so that a folded `gamma(<literal>)` produces the
  same value as the BE. commons-math3's `Gamma.gamma` saturates to Infinity at 165, where
  `std::tgamma` still returns a finite 3.29e293 (it stays finite up to 171), so positive inputs are
  evaluated as `exp(logGamma(x))`. Negative non-integers have no overflow problem and use
  `Gamma.gamma`.

### Release note

Add the `gamma` scalar function. `gamma(n)` is `(n - 1)!` for a positive integer `n`; `gamma(0)`
and the negative integers return NULL.

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test
    - [x] Manual test (add detailed scripts or steps below)
    - [ ] No need to test or manual test. Explain why:
- Behavior changed:
    - [x] No.
    - [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
    - [ ] No.
    - [x] Yes. <!-- REPLACE THIS WITH THE DOCS PR LINK, e.g. https://github.com/apache/doris-website/pull/XXXX -->

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label

Manual test:

- `select gamma(5), gamma(0.5), gamma(-1.5), gamma(0), gamma(-1), gamma(-3);` returns
  `24.000000000000004, 1.772453850905516, 2.3632718012073544, NULL, NULL, NULL`, and the same
  values are returned with `set debug_skip_fold_constant=true`, i.e. constant folding and BE
  execution agree.
- `gamma(cast('nan' as double))` is NaN, `gamma(cast('inf' as double))` is Infinity,
  `gamma(cast('-inf' as double))` is NULL, `gamma(165)` is 3.287218585534318E293,
  `gamma(171)` is 7.257415615308056E306 and `gamma(172)` is Infinity.
- `explain select gamma(v) from t where gamma(v) > 10;` still plans an olap scan with the
  predicate and the projection applied.
@RH211-sys

Copy link
Copy Markdown
Author

Friendly ping @morrySnow @924060929 @englefly @starocean999 (Code Owners of
fe/fe-core/src/main/java/org/apache/doris/nereids) and @yiguolei (recent committer on
be/src/exprs/function/math.cpp).

This PR adds the gamma scalar function. As a first-time contributor the CI workflows are still
waiting for approval, so no checks have started yet; I also posted a request to
dev@doris.apache.org. Could someone approve the workflows and take a look?

Local validation: full sh build.sh --be --fe on the dev branch, BE UT
MathFunctionTest.gamma_test passes, the new regression suite test_gamma passes in compare mode,
and the folded/unfolded values agree.

Docs PR: apache/doris-website#4140

Thanks!

@yiguolei

Copy link
Copy Markdown
Contributor

/review

924060929
924060929 previously approved these changes Sep 21, 2026
@RH211-sys

Copy link
Copy Markdown
Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27904 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 6ef21f08893bb01581b5addc2e439f3de309df94, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17723	3882	3860	3860
q2	2153	352	304	304
q3	10100	1380	824	824
q4	4685	479	351	351
q5	7459	831	540	540
q6	175	168	142	142
q7	755	788	594	594
q8	9292	1400	1534	1400
q9	5392	4235	4178	4178
q10	6836	1326	1015	1015
q11	434	273	243	243
q12	636	421	304	304
q13	18023	2608	2001	2001
q14	264	256	234	234
q15	q16	746	723	657	657
q17	1812	1171	1074	1074
q18	6489	5600	5533	5533
q19	1326	1248	1008	1008
q20	480	414	262	262
q21	5811	3390	3074	3074
q22	466	374	306	306
Total cold run time: 101057 ms
Total hot run time: 27904 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4658	5072	4449	4449
q2	747	579	552	552
q3	4808	5133	4600	4600
q4	2195	2320	1471	1471
q5	4495	4385	4551	4385
q6	233	184	136	136
q7	1811	1698	1538	1538
q8	2306	2072	2035	2035
q9	7310	7248	7252	7248
q10	3683	3611	3153	3153
q11	603	393	343	343
q12	701	701	501	501
q13	2275	2614	1991	1991
q14	263	274	256	256
q15	q16	671	685	606	606
q17	7307	6701	6601	6601
q18	11807	11004	11694	11004
q19	1097	988	1038	988
q20	2196	2189	1912	1912
q21	5034	4116	4308	4116
q22	510	473	407	407
Total cold run time: 64710 ms
Total hot run time: 58292 ms

@morrySnow

Copy link
Copy Markdown
Contributor

/review Check whether the calculation logic of fe and be is strictly consistent, especially paying attention to boundary values, positive and negative zero, positive and negative infinity, nan, and handling precision overflow.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152298 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 6ef21f08893bb01581b5addc2e439f3de309df94, data reload: false

query5	4318	595	468	468
query6	434	209	190	190
query7	4820	528	285	285
query8	327	186	163	163
query9	8824	3921	3921	3921
query10	474	311	270	270
query11	5827	3542	3203	3203
query12	147	90	87	87
query13	1246	562	391	391
query14	6478	4478	4239	4239
query14_1	3982	3931	3933	3931
query15	208	201	183	183
query16	955	428	429	428
query17	920	678	542	542
query18	2425	464	338	338
query19	204	191	141	141
query20	84	83	80	80
query21	218	133	113	113
query22	13061	12940	12761	12761
query23	14053	12890	12445	12445
query23_1	12548	12502	12351	12351
query24	7217	1203	723	723
query24_1	702	704	721	704
query25	582	451	386	386
query26	1272	326	169	169
query27	2713	556	317	317
query28	4583	1989	1998	1989
query29	1690	767	540	540
query30	309	227	185	185
query31	881	759	636	636
query32	148	93	95	93
query33	555	317	257	257
query34	1215	1159	646	646
query35	718	744	633	633
query36	802	821	719	719
query37	147	111	92	92
query38	1824	1763	1682	1682
query39	696	687	667	667
query39_1	676	670	666	666
query40	225	126	110	110
query41	72	73	68	68
query42	103	98	98	98
query43	340	348	300	300
query44	1405	706	723	706
query45	192	178	209	178
query46	1063	1195	706	706
query47	1484	1495	1417	1417
query48	373	400	283	283
query49	578	409	282	282
query50	1000	359	263	263
query51	10532	10611	10501	10501
query52	86	89	75	75
query53	238	250	183	183
query54	250	204	185	185
query55	81	76	68	68
query56	228	207	212	207
query57	1430	1498	1377	1377
query58	282	261	245	245
query59	2010	2034	1867	1867
query60	288	238	229	229
query61	151	152	145	145
query62	407	318	267	267
query63	220	178	183	178
query64	2829	980	828	828
query65	3463	3424	3400	3400
query66	1799	417	306	306
query67	20035	20079	19787	19787
query68	3173	1408	902	902
query69	401	301	261	261
query70	922	862	820	820
query71	292	236	214	214
query72	2649	2567	2207	2207
query73	858	794	432	432
query74	4653	4497	4281	4281
query75	2293	2275	1934	1934
query76	2329	1123	801	801
query77	367	411	302	302
query78	9055	8998	8465	8465
query79	1395	1144	741	741
query80	1239	476	369	369
query81	586	339	280	280
query82	654	156	126	126
query83	293	227	197	197
query84	310	144	111	111
query85	893	485	398	398
query86	406	237	230	230
query87	1998	1951	1834	1834
query88	3689	2746	2708	2708
query89	364	284	244	244
query90	1942	185	183	183
query91	166	161	131	131
query92	107	95	90	90
query93	1564	1428	775	775
query94	711	352	291	291
query95	670	366	343	343
query96	1005	794	354	354
query97	2421	2395	2326	2326
query98	159	149	144	144
query99	742	728	623	623
Total cold run time: 237424 ms
Total hot run time: 152298 ms

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes. The gamma registration, signature, visitor hook, and shared nullable/const execution wrapper are structurally consistent with analogous functions, but the FE constant-folding path is not equivalent to the BE implementation, and the new exact fixtures encode the wrong implementation's values.

Critical checkpoints:

  • Task goal: the PR adds gamma and maps zero/negative-integer poles to NULL. That common-path behavior is implemented, but FE folding can change finite values and even NaN/Infinity classification relative to BE execution.
  • Correctness: MAIN-1 shows concrete Commons Math 3.6.1 versus std::tgamma divergences for ordinary values, large negative non-integers, and the positive subnormal overflow boundary.
  • Tests: MAIN-2 shows the BE unit data and generated regression output use FE exp(logGamma) values while the BE test compares std::tgamma results exactly; these expectations are platform-dependent and fail on this runner's libm.
  • Scope/safety: no new concurrency, persistence, configuration, FE-BE protocol, transaction, or data-write lifecycle was introduced. The wrapper's nullable/const null-map flow and Nereids registration were independently traced with no additional issue.
  • Validation: this was a static review per the supplied prompt; no repository builds or tests were run. The numerical findings were independently reproduced against the declared Commons Math 3.6.1 dependency and the runner's libm. No user-provided focus points were supplied.

Please resolve the two inline findings, then regenerate/extend parity coverage for positive, negative, and subnormal boundary cases before re-review.

}
if (Double.isInfinite(x)) {
// +inf overflows to itself; -inf is treated as a negative integer, i.e. a pole.
return x > 0 ? new DoubleLiteral(Double.POSITIVE_INFINITY)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gamma is folded here with Commons Math, but execution uses std::tgamma in BE. These implementations do not agree for all finite doubles: Commons Math 3.6.1 gives gamma(-150.5) = -0.0 while BE returns about -4.478447658150641e-264, and gamma(-1000.5) = NaN while BE returns signed zero; near the positive subnormal overflow boundary (0x0.3ffffffffffffp-1022) FE produces a finite max-double value while BE returns Infinity. Even ordinary values differ (gamma(10) folds to 362879.9999999998 versus BE 362880.0). A literal query can therefore change rows, comparisons, and overflow/NaN classification when constant folding is toggled. Please use a numerically equivalent implementation/shared boundary or disable folding for inputs that cannot be proven equivalent, and add parity coverage for these domains.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this function does not contribute to partition pruning and bucket pruning, and cannot simply align the implementations of fe and be, then not implementing the version of fe might be a better choice.

{{2.5}, 1.329340388179137},
{{-0.5}, -3.5449077018110318},
{{-1.5}, 2.3632718012073544},
{{-2.5}, -0.94530872048294179},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These exact expected values are from the FE exp(logGamma) route, not the registered BE call. On this runner std::tgamma(5) is 24.0, tgamma(10) is 362880.0, tgamma(-1.5) is 2.363271801207355, tgamma(-2.5) is -0.9453087204829419, and tgamma(171) is 7.257415615307999e306, while this test expects different doubles. check_function compares ColumnFloat64 values exactly, so the unit test (and the generated regression fixture) is platform-dependent and can fail. Please regenerate expectations from the BE implementation or use a documented tolerance/portable oracle.

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.99 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 6ef21f08893bb01581b5addc2e439f3de309df94, data reload: false

query1	0.01	0.01	0.01
query2	0.10	0.05	0.05
query3	0.26	0.14	0.13
query4	1.61	0.13	0.14
query5	0.24	0.23	0.21
query6	1.16	0.95	0.96
query7	0.04	0.00	0.00
query8	0.06	0.04	0.04
query9	0.39	0.34	0.33
query10	0.55	0.54	0.55
query11	0.20	0.15	0.14
query12	0.17	0.16	0.14
query13	0.46	0.46	0.46
query14	0.95	0.97	0.96
query15	0.60	0.61	0.59
query16	0.34	0.30	0.31
query17	1.10	1.10	1.08
query18	0.22	0.20	0.21
query19	2.05	1.96	1.95
query20	0.02	0.01	0.01
query21	15.41	0.21	0.13
query22	4.86	0.05	0.05
query23	16.12	0.31	0.13
query24	2.90	0.42	0.32
query25	0.11	0.05	0.04
query26	0.74	0.22	0.14
query27	0.05	0.04	0.03
query28	3.54	0.75	0.34
query29	12.50	4.00	3.19
query30	0.28	0.15	0.15
query31	2.77	0.57	0.31
query32	3.23	0.59	0.48
query33	3.21	3.22	3.34
query34	15.58	3.89	3.26
query35	3.23	3.22	3.23
query36	0.56	0.42	0.41
query37	0.08	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.04	0.04
query40	0.19	0.16	0.13
query41	0.09	0.03	0.04
query42	0.04	0.02	0.02
query43	0.04	0.04	0.03
Total cold run time: 96.15 s
Total hot run time: 23.99 s

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes.

The gamma registration, signature, visitor dispatch, nullable typing, constant/null adapters, and BE registration are structurally consistent. This exact-head review converged after two full normal and risk-focused passes.

Findings:

  • Existing inline comments 4058837042 and 4058837046 already cover the blocking FE/BE numerical divergence and the nonportable exact libm unit oracle, so I did not duplicate them.
  • This review adds one distinct test defect: the supposed negative-zero row stores positive zero, leaving the requested signed-zero boundary untested.

Checkpoint conclusions:

  • Goal and scope: the patch is focused and structurally wires gamma(DOUBLE) to Nullable(DOUBLE), but strict FE/BE numerical equivalence is not met per the existing thread.
  • Parallel paths and conditions: FE folding and BE execution were traced through their full call chains. Pole handling for signed zero and finite negative integers, plus explicit NaN and infinity branches, is structurally aligned; the remaining numerical boundary failures are already covered by the existing thread.
  • Tests: result cardinalities, ordering, nullable/constant shapes, and generated output are internally consistent. The exact libm oracle is covered by an existing thread; the new inline identifies the ineffective signed-zero input.
  • Concurrency, lifecycle, configuration, compatibility, persistence, transactions/data writes, protocol/storage format, and observability: no new mechanism requiring a separate finding was introduced. No separate performance or error-handling issue was substantiated.
  • Validation: static review only, as required; no Doris build or test suite was run. Numerical behavior was independently probed with temporary review-only programs, not a Doris execution.

sql "truncate table test_gamma"
sql """ insert into test_gamma values
(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 10, 10),
(7, 0, 0), (8, -0, -0), (9, -1, -1), (10, -2, -2), (11, -3, -3),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Construct an actual negative-zero input. Both occurrences of -0 here are parsed as integer unary minus (0 - 0) before the DOUBLE column cast, so this row stores +0.0 and duplicates row 7. Please use an explicit DOUBLE construction such as cast('-0.0' as double) and add a sign-sensitive check (for example signbit(b)) so the requested negative-zero boundary is genuinely exercised before relying on the gamma result.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 4.35% (1/23) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.29% (34371/45055)
Line Coverage 61.16% (385660/630627)
Region Coverage 57.60% (324908/564125)
Branch Coverage 58.34% (147884/253465)

### What problem does this PR solve?

Related issue: [apache#48203](apache#48203)

Problem Summary:

The FE folded `gamma(<literal>)` through commons-math3 while the BE computes it with
`std::tgamma`. The two are independent implementations that cannot be kept aligned, so a
folded constant could differ from the value the BE produces. Measured on the Doris build
environment:

- `gamma(-1000.5)` is NaN from the FE and -0.0 from the BE, a different classification;
- `gamma(-150.5)` is 0.0 from the FE and -4.4784476581511713e-264 from the BE;
- `gamma(10)` is 362879.9999999998 from the FE and 362880.00000000047 from the BE, about 11 ulp.

`gamma` feeds neither partition nor bucket pruning, so the folding buys nothing. Remove it
(`NumericArithmetic.gamma` and the commons-math3 import it needed) and let the BE stay the
only implementation. There is then a single evaluation path: the default session, a session
with `debug_skip_fold_constant=true`, a session with `enable_fold_constant_by_be=true` and a
query that reads `gamma` of a table column all return identical values for the boundary inputs
below (0, -0.0, negative integers, +/-infinity, NaN, 165/170/171/171.5/171.8/172/1e308, the
smallest subnormal and the smallest normal, 1e-300, and large negative non-integers).

Also in this commit:

- The negative-zero row of the regression suite was written as the integer `-0`, which is
  stored as +0.0 and silently duplicated the row holding 0.0. It now uses
  `cast('-0.0' as double)` and is guarded by a `signbit` assertion, so a wrong test value fails
  instead of being recorded in the generated .out file. The suite also gains the boundary
  classes it was missing: inputs whose reciprocal overflows (1e-300, 5e-324,
  2.2250738585072014e-308), the overflow onset (171.5 is finite, 171.8 is Infinity) and large
  negative non-integers that underflow to -0.0 (-1000.5) or to a subnormal (-171.5).
- The near-zero rows hold what libm's tgamma returns, about 1e-14 relative away from the
  correctly rounded value, which is inside the 1e-8 relative tolerance the framework applies to
  DOUBLE cells. The two properties that tolerance cannot see are asserted directly: the sign of
  a result that underflows to zero, and a subnormal result that must not collapse to zero.
- `testFoldConst` passes by construction now that nothing is folded, so it is kept as a guard
  for a folding that might come back, and its last two columns are BOOLEAN
  (`signbit(gamma(-1000.5))`, `gamma(-171.5) > 0`). checkCell compares BOOLEAN cells exactly,
  while its double path would not notice a folding that flipped the sign of an underflowed zero
  (0.0 against -0.0 divides by a zero magnitude) or let a subnormal collapse to zero (the
  decimal-place fallback accepts it).
- `math.cpp` cited a MySQL `gamma` anchor, but MySQL has no `gamma` function. The comment now
  states the convention actually followed: a domain error such as a pole returns NULL, as
  `sqrt(-1)` and `ln(0)` do, and only overflow returns Infinity.
- The BE unit test also pins -0.0 as a pole.
- The new FE statements are covered by `GammaTest`, which exercises the signature, the
  nullability, the implicit cast of the argument and the visitor dispatch through
  `withChildren`. This is what `check_coverage_fe` reports as uncovered.

### Release note

None

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test
    - [x] Manual test (the boundary matrix described above)
    - [ ] No need to test or manual test. Explain why:
- Behavior changed:
    - [x] Yes: `gamma(<literal>)` is no longer constant folded in the FE, it is computed by the
      BE like every other invocation. The values returned to the client are unchanged.
- Does this need documentation?
    - [x] Yes: apache/doris-website#4140
@RH211-sys

Copy link
Copy Markdown
Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27872 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 855f0c9343936e3e0253649bc118b5ed3792bcba, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17625	3841	3821	3821
q2	2172	362	300	300
q3	10121	1459	815	815
q4	4682	480	349	349
q5	7468	841	553	553
q6	175	179	139	139
q7	745	782	594	594
q8	9362	1517	1607	1517
q9	5478	4222	4194	4194
q10	6820	1333	1015	1015
q11	442	278	239	239
q12	636	426	296	296
q13	18054	2621	1980	1980
q14	262	250	231	231
q15	q16	720	714	657	657
q17	1719	1090	1020	1020
q18	6546	5604	5566	5566
q19	1317	1242	1081	1081
q20	481	410	262	262
q21	5707	3301	2931	2931
q22	454	370	312	312
Total cold run time: 100986 ms
Total hot run time: 27872 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4662	4737	4417	4417
q2	749	581	531	531
q3	4854	5171	4528	4528
q4	2303	2408	1471	1471
q5	4586	4391	4575	4391
q6	221	181	131	131
q7	1849	1714	1504	1504
q8	2301	2115	2042	2042
q9	7367	7222	7206	7206
q10	3697	3639	3101	3101
q11	518	375	338	338
q12	713	711	498	498
q13	2297	2605	2004	2004
q14	264	270	249	249
q15	q16	661	683	601	601
q17	7336	6873	6662	6662
q18	11841	11108	11818	11108
q19	1113	992	1004	992
q20	2198	2191	1914	1914
q21	5023	4131	4299	4131
q22	511	450	398	398
Total cold run time: 65064 ms
Total hot run time: 58217 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152150 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 855f0c9343936e3e0253649bc118b5ed3792bcba, data reload: false

query5	4339	620	461	461
query6	429	221	195	195
query7	4822	544	305	305
query8	332	181	168	168
query9	8819	4015	3991	3991
query10	443	302	246	246
query11	5849	3570	3233	3233
query12	143	90	87	87
query13	1239	556	374	374
query14	6523	4494	4203	4203
query14_1	3934	3947	3931	3931
query15	198	194	176	176
query16	985	451	379	379
query17	910	662	541	541
query18	2423	460	336	336
query19	210	180	150	150
query20	87	81	81	81
query21	224	133	116	116
query22	13080	13167	12873	12873
query23	14059	12942	12504	12504
query23_1	12501	12524	12481	12481
query24	7225	1183	667	667
query24_1	693	710	764	710
query25	556	434	376	376
query26	1309	326	174	174
query27	2630	552	333	333
query28	4572	1962	1958	1958
query29	1641	760	526	526
query30	299	228	185	185
query31	900	766	648	648
query32	152	96	104	96
query33	525	326	256	256
query34	1194	1122	626	626
query35	732	760	647	647
query36	802	808	697	697
query37	153	103	88	88
query38	1839	1776	1711	1711
query39	701	696	678	678
query39_1	638	661	647	647
query40	229	122	105	105
query41	78	73	69	69
query42	95	97	94	94
query43	335	352	306	306
query44	1350	715	714	714
query45	194	180	161	161
query46	1043	1161	722	722
query47	1485	1506	1415	1415
query48	399	393	292	292
query49	606	425	305	305
query50	965	351	258	258
query51	10565	10752	10314	10314
query52	91	87	77	77
query53	243	252	183	183
query54	266	225	206	206
query55	81	76	75	75
query56	231	227	239	227
query57	1466	1358	1423	1358
query58	289	265	262	262
query59	2011	2090	1873	1873
query60	294	251	235	235
query61	169	168	182	168
query62	387	319	269	269
query63	218	171	173	171
query64	2803	957	785	785
query65	3484	3410	3437	3410
query66	1806	432	315	315
query67	20009	20178	19821	19821
query68	3084	1476	863	863
query69	392	310	262	262
query70	907	816	812	812
query71	285	247	226	226
query72	2602	2473	1944	1944
query73	821	778	416	416
query74	4622	4498	4296	4296
query75	2285	2293	1940	1940
query76	2318	1101	725	725
query77	358	389	300	300
query78	9110	9086	8432	8432
query79	1326	1181	735	735
query80	587	449	373	373
query81	553	329	283	283
query82	631	162	121	121
query83	296	220	198	198
query84	325	141	113	113
query85	835	454	365	365
query86	327	234	233	233
query87	2000	1980	1843	1843
query88	3623	2737	2710	2710
query89	367	284	248	248
query90	1913	180	180	180
query91	172	164	122	122
query92	103	83	91	83
query93	1459	1431	895	895
query94	531	323	281	281
query95	674	348	357	348
query96	1024	809	322	322
query97	2441	2405	2330	2330
query98	162	152	141	141
query99	716	729	626	626
Total cold run time: 235803 ms
Total hot run time: 152150 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 855f0c9343936e3e0253649bc118b5ed3792bcba, data reload: false

query1	0.01	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.14	0.13
query4	1.61	0.14	0.14
query5	0.25	0.22	0.21
query6	1.17	0.96	0.94
query7	0.04	0.00	0.00
query8	0.05	0.04	0.04
query9	0.39	0.34	0.34
query10	0.54	0.54	0.59
query11	0.20	0.14	0.16
query12	0.19	0.15	0.15
query13	0.46	0.46	0.48
query14	0.95	0.93	0.95
query15	0.61	0.60	0.58
query16	0.32	0.32	0.32
query17	1.09	1.05	1.05
query18	0.22	0.20	0.19
query19	2.06	1.94	1.93
query20	0.02	0.02	0.01
query21	15.50	0.22	0.14
query22	4.78	0.05	0.06
query23	16.13	0.31	0.12
query24	2.93	0.43	0.33
query25	0.10	0.05	0.05
query26	0.73	0.20	0.16
query27	0.05	0.04	0.03
query28	3.57	0.84	0.37
query29	12.46	4.05	3.21
query30	0.27	0.18	0.15
query31	2.78	0.56	0.31
query32	3.23	0.60	0.49
query33	3.19	3.19	3.18
query34	15.55	3.89	3.30
query35	3.23	3.19	3.22
query36	0.56	0.44	0.43
query37	0.10	0.06	0.07
query38	0.04	0.04	0.03
query39	0.04	0.03	0.04
query40	0.17	0.14	0.14
query41	0.08	0.03	0.02
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.11 s
Total hot run time: 24 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.31% (34372/45044)
Line Coverage 61.19% (385775/630472)
Region Coverage 57.60% (324936/564132)
Branch Coverage 58.41% (148018/253417)

@yiguolei

Copy link
Copy Markdown
Contributor

@RH211-sys please also add document for this function

…ge gate

### What problem does this PR solve?

Related issue: [apache#48203](apache#48203)

Problem Summary:

`check_coverage_fe` requires the increment line coverage to be 100% and failed with
`Gamma.java  90.00% (9/10)`, even though every executable line of the class was reached.

The `Preconditions.checkArgument(children.size() == 1)` in `withChildren` is the only branch in
the class. The line itself executes, but its failing direction never does, and the coverage
portal reports a partially covered line as uncovered - locally the same run reports
`LINE_MISSED=0` while `BRANCH_MISSED=1` and `INSTRUCTION_MISSED=1`.

Exercise the failing direction too, so the line is fully covered. Verified with
`run-fe-ut.sh --run --coverage org.apache.doris.nereids.trees.expressions.functions.scalar.GammaTest`:
Gamma now reports instruction 0/48 missed, branch 0/2 missed, line 0/10 missed, and the four
tests of GammaTest pass.

### Release note

None
@RH211-sys

Copy link
Copy Markdown
Author

@yiguolei The documentation is in apache/doris-website#4140 — it was
opened together with this change and is linked in the PR description now. I have just updated it.

@RH211-sys

Copy link
Copy Markdown
Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27943 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1197c62327b83898337267e8be15898977072c08, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17888	3796	3798	3796
q2	2203	359	290	290
q3	10108	1416	799	799
q4	4687	483	351	351
q5	7481	819	570	570
q6	184	168	136	136
q7	750	810	597	597
q8	9313	1567	1494	1494
q9	5425	4203	4204	4203
q10	6825	1339	1027	1027
q11	435	268	238	238
q12	627	417	298	298
q13	18091	2605	2001	2001
q14	268	261	235	235
q15	q16	729	719	652	652
q17	1725	1159	995	995
q18	6444	5641	5538	5538
q19	1295	1219	1029	1029
q20	506	388	259	259
q21	5768	3315	3123	3123
q22	469	368	312	312
Total cold run time: 101221 ms
Total hot run time: 27943 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4603	4665	4347	4347
q2	722	548	531	531
q3	4805	5068	4710	4710
q4	2206	2308	1454	1454
q5	4623	4348	4587	4348
q6	221	169	127	127
q7	1760	1683	1476	1476
q8	2353	2043	2031	2031
q9	7226	7334	7171	7171
q10	3695	3608	3150	3150
q11	513	366	349	349
q12	708	709	504	504
q13	2255	2583	1984	1984
q14	269	272	244	244
q15	q16	670	682	607	607
q17	7252	6707	6667	6667
q18	11897	11021	11655	11021
q19	1095	973	973	973
q20	2201	2169	1935	1935
q21	4969	4150	4322	4150
q22	499	462	389	389
Total cold run time: 64542 ms
Total hot run time: 58168 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152466 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 1197c62327b83898337267e8be15898977072c08, data reload: false

query5	4359	616	471	471
query6	451	230	201	201
query7	4807	536	302	302
query8	328	188	169	169
query9	8836	3960	3972	3960
query10	467	312	261	261
query11	5919	3522	3234	3234
query12	160	91	86	86
query13	1278	566	418	418
query14	6579	4491	4221	4221
query14_1	3972	3971	3883	3883
query15	202	200	176	176
query16	1008	428	442	428
query17	885	635	532	532
query18	2442	474	329	329
query19	204	176	157	157
query20	87	86	80	80
query21	219	129	113	113
query22	13013	12909	12899	12899
query23	13927	12958	12343	12343
query23_1	12471	12482	12570	12482
query24	7347	1165	645	645
query24_1	694	694	782	694
query25	536	410	355	355
query26	1267	314	156	156
query27	2701	556	330	330
query28	4574	1957	1942	1942
query29	1653	722	513	513
query30	298	221	178	178
query31	887	755	628	628
query32	153	94	86	86
query33	505	297	246	246
query34	1179	1118	593	593
query35	723	751	633	633
query36	804	789	732	732
query37	143	103	90	90
query38	1808	1757	1709	1709
query39	714	681	656	656
query39_1	660	670	650	650
query40	218	118	102	102
query41	82	71	64	64
query42	98	92	92	92
query43	327	341	297	297
query44	1364	705	699	699
query45	178	176	164	164
query46	999	1231	696	696
query47	1497	1474	1398	1398
query48	395	411	292	292
query49	586	406	297	297
query50	935	364	249	249
query51	10379	10435	10604	10435
query52	85	88	75	75
query53	250	253	176	176
query54	267	194	203	194
query55	85	77	70	70
query56	266	215	219	215
query57	1405	1476	1444	1444
query58	286	254	246	246
query59	1975	2060	1854	1854
query60	279	235	223	223
query61	151	150	146	146
query62	398	327	275	275
query63	230	170	177	170
query64	2808	1024	823	823
query65	3466	3540	3425	3425
query66	1782	413	301	301
query67	19938	19911	19710	19710
query68	3195	1521	957	957
query69	394	298	281	281
query70	892	792	801	792
query71	303	236	216	216
query72	2691	2595	2396	2396
query73	827	784	412	412
query74	4617	4467	4305	4305
query75	2305	2295	1949	1949
query76	2330	1121	703	703
query77	361	405	312	312
query78	9030	8973	8470	8470
query79	1186	1225	774	774
query80	556	490	395	395
query81	523	328	283	283
query82	278	164	126	126
query83	223	245	202	202
query84	289	156	121	121
query85	917	451	380	380
query86	279	236	231	231
query87	1971	1959	1837	1837
query88	3576	2681	2684	2681
query89	315	284	248	248
query90	2128	180	164	164
query91	179	154	127	127
query92	102	83	89	83
query93	1390	1393	865	865
query94	529	342	300	300
query95	682	390	414	390
query96	1052	831	347	347
query97	2421	2440	2322	2322
query98	175	151	150	150
query99	717	723	617	617
Total cold run time: 235101 ms
Total hot run time: 152466 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.01 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 1197c62327b83898337267e8be15898977072c08, data reload: false

query1	0.01	0.00	0.00
query2	0.09	0.06	0.05
query3	0.26	0.14	0.14
query4	1.60	0.13	0.14
query5	0.24	0.21	0.22
query6	1.16	0.95	0.93
query7	0.04	0.00	0.00
query8	0.06	0.04	0.04
query9	0.39	0.33	0.37
query10	0.58	0.55	0.60
query11	0.21	0.14	0.14
query12	0.18	0.14	0.14
query13	0.47	0.47	0.47
query14	0.95	0.93	0.96
query15	0.62	0.61	0.59
query16	0.31	0.32	0.31
query17	1.16	1.11	1.11
query18	0.22	0.19	0.21
query19	2.12	1.97	1.89
query20	0.02	0.01	0.01
query21	15.50	0.22	0.14
query22	4.89	0.05	0.06
query23	16.13	0.30	0.12
query24	2.98	0.42	0.34
query25	0.12	0.05	0.05
query26	0.77	0.20	0.14
query27	0.05	0.04	0.03
query28	3.49	0.77	0.35
query29	12.46	4.10	3.21
query30	0.28	0.15	0.15
query31	2.78	0.55	0.30
query32	3.24	0.58	0.49
query33	3.22	3.20	3.21
query34	15.74	3.92	3.29
query35	3.18	3.22	3.23
query36	0.55	0.44	0.43
query37	0.09	0.06	0.07
query38	0.05	0.03	0.03
query39	0.04	0.03	0.04
query40	0.17	0.14	0.14
query41	0.09	0.04	0.03
query42	0.03	0.02	0.03
query43	0.04	0.03	0.03
Total cold run time: 96.58 s
Total hot run time: 24.01 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (12/12) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.15% (34300/45044)
Line Coverage 61.07% (385022/630474)
Region Coverage 57.52% (324496/564142)
Branch Coverage 58.28% (147705/253423)

@RH211-sys

Copy link
Copy Markdown
Author

run buildall

@RH211-sys

Copy link
Copy Markdown
Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (12/12) 🎉
Increment coverage report
Complete coverage report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants