-- validation of percentile values -- correct values SELECT tdigest_percentile(1.0, 10, 0.0); SELECT tdigest_percentile(1.0, 10, 0.1); SELECT tdigest_percentile(1.0, 10, 0.5); SELECT tdigest_percentile(1.0, 10, 0.9); SELECT tdigest_percentile(1.0, 10, 1.0); SELECT tdigest_percentile(1.0, 10, ARRAY[0.0, 0.1, 0.5, 0.9, 1.0]); -- out of range values SELECT tdigest_percentile(1.0, 10, -1.0); SELECT tdigest_percentile(1.0, 10, 1.5); SELECT tdigest_percentile(1.0, 10, ARRAY[0.0, -1.0, 0.5, 0.9, 1.0]); SELECT tdigest_percentile(1.0, 10, ARRAY[0.0, 0.1, 0.5, 0.9, 1.5]); -- NaN SELECT tdigest_percentile(1.0, 10, 'NaN'::double precision); SELECT tdigest_percentile(1.0, 10, ARRAY[0.0, 'NaN'::double precision, 0.5, 0.9, 1.0]); -- infinite values SELECT tdigest_percentile(1.0, 10, 'infinity'::double precision); SELECT tdigest_percentile(1.0, 10, '-infinity'::double precision); SELECT tdigest_percentile(1.0, 10, ARRAY[0.0, 'infinity'::double precision, 0.5, 0.9, 1.0]); SELECT tdigest_percentile(1.0, 10, ARRAY[0.0, '-infinity'::double precision, 0.5, 0.9, 1.0]); -- more tests SELECT tdigest_percentile(1.0::double precision, 10, 'NaN'::double precision); SELECT tdigest_percentile(1.0::double precision, 10, '-infinity'::double precision); SELECT tdigest_percentile(1.0::double precision, 10, 'infinity'::double precision); SELECT tdigest_percentile(1.0::double precision, 10, ARRAY[0.5, 'NaN']::double precision[]); SELECT tdigest_percentile(1.0::double precision, 10, ARRAY[0.5, '-infinity']::double precision[]); SELECT tdigest_percentile(1.0::double precision, 10, ARRAY[0.5, 'infinity']::double precision[]); SELECT tdigest_percentile('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, 'NaN'::double precision); SELECT tdigest_percentile('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, '-infinity'::double precision); SELECT tdigest_percentile('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, 'infinity'::double precision); SELECT tdigest_percentile('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, ARRAY[0.5, 'NaN']::double precision[]); SELECT tdigest_percentile('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, ARRAY[0.5, '-infinity']::double precision[]); SELECT tdigest_percentile('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, ARRAY[0.5, 'infinity']::double precision[]); -- trim thresholds are checked too SELECT tdigest_avg(1.0::double precision, 10, 'NaN'::double precision, 1.0); SELECT tdigest_avg(1.0::double precision, 10, '-infinity'::double precision, 1.0); SELECT tdigest_avg(1.0::double precision, 10, 'infinity'::double precision, 1.0); SELECT tdigest_digest_sum('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, 0.0, 'NaN'::double precision); SELECT tdigest_digest_sum('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, 0.0, '-infinity'::double precision); SELECT tdigest_digest_sum('flags 1 count 1 compression 10 centroids 1 (1, 1)'::tdigest, 0.0, 'infinity'::double precision); -- validation of input values -- input functions must reject NaN / infinity means in various places SELECT 'flags 1 count 1 compression 10 centroids 1 (NaN, 1)'::tdigest; SELECT 'flags 1 count 1 compression 10 centroids 1 (infinity, 1)'::tdigest; SELECT 'flags 1 count 1 compression 10 centroids 1 (-infinity, 1)'::tdigest; -- the aggregates building the digest have to reject NaN / infinity too SELECT tdigest('NaN'::float8, 10); SELECT tdigest('infinity'::float8, 10); SELECT tdigest('-infinity'::float8, 10); -- same for the value/count API SELECT tdigest('NaN'::float8, 50::bigint, 10); SELECT tdigest('NaN'::float8, 200::bigint, 10); SELECT tdigest('Infinity'::float8, 200::bigint, 10); SELECT tdigest('-Infinity'::float8, 200::bigint, 10); -- t-digest extreme enough for the percentile to fall to the right of the last centroid SELECT tdigest_percentile('flags 1 count 4611686018427388928 compression 10 centroids 3 (1, 4611686018427387904) (2, 512) (3, 512)'::tdigest, 0.9999999999999998::double precision); -- same centroid, but the percentile falls in between the second and third centroid SELECT tdigest_percentile('flags 1 count 4611686018427388928 compression 10 centroids 3 (1, 4611686018427387904) (2, 512) (3, 512)'::tdigest, ARRAY[0.0, 0.5, 0.9999999999999996, 1.0]::double precision[]); -- the same digest with other compressions, to show the compression does not affect this -- the compaction leaves the digest alone for all compression values SELECT c AS compression, tdigest_percentile(('flags 1 count 4611686018427388928 compression ' || c || ' centroids 3 (1, 4611686018427387904) (2, 512) (3, 512)')::tdigest, 0.9999999999999998::double precision) FROM (VALUES (10), (100), (1000), (10000)) v(c) GROUP BY c ORDER BY c; -- make sure finite inputs do not not produce infinite centroids SELECT tdigest_count(tdigest(v, 10)) FROM (SELECT (CASE WHEN i % 2 = 0 THEN 1e308 ELSE 1e307 END)::float8 AS v FROM generate_series(1,200) i) x; -- make sure finite inputs do not result in NaN means WITH x AS (SELECT (CASE i % 4 WHEN 0 THEN -1e308 WHEN 1 THEN -1e307 WHEN 2 THEN 1e307 ELSE 1e308 END)::float8 AS v FROM generate_series(1,400) i) SELECT tdigest_percentile(v,10,0.5) FROM x; -- extreme digest - make sure we can read the output we produced SELECT tdigest_count((SELECT tdigest(v, c, 10) FROM (VALUES (1e307::float8, 1000000::bigint), (1e308::float8, 1000000::bigint)) x(v, c))::text::tdigest); -- extreme digest - overflow/rounding issue in tdigest_compute_quantiles SELECT tdigest_percentile('flags 1 count 204745659738676291 compression 100 centroids 3 (5360.6421513780951, 96854112897858161) (5670.4376627340216, 36597233557612361) (5670.4376627340216, 71294313283205769)'::tdigest, 0.56241841621276667); -- extreme digest - overflow/rounding issue in tdigest_compute_quantiles_of SELECT tdigest_percentile_of('flags 1 count 467525031770889061 compression 100 centroids 5 (-714.32532319527991, 372151463885287745) (-649.22210009079686, 12983637447676689) (-613.86327584091737, 82389930437924625) (-554.7460856469786, 1) (-497.74083276256061, 1)'::tdigest, -517.61603495911652);