-- -- FLOAT8 -- CREATE TABLE FLOAT8_TBL(f1 float8); INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); -- test for underflow and overflow handling SELECT '10e400'::float8; ERROR: "10e400" is out of range for type double precision LINE 1: SELECT '10e400'::float8; ^ SELECT '-10e400'::float8; ERROR: "-10e400" is out of range for type double precision LINE 1: SELECT '-10e400'::float8; ^ SELECT '10e-400'::float8; ERROR: "10e-400" is out of range for type double precision LINE 1: SELECT '10e-400'::float8; ^ SELECT '-10e-400'::float8; ERROR: "-10e-400" is out of range for type double precision LINE 1: SELECT '-10e-400'::float8; ^ -- test smallest normalized input SELECT float8send('2.2250738585072014E-308'::float8); float8send -------------------- \x0010000000000000 (1 row) -- bad input INSERT INTO FLOAT8_TBL(f1) VALUES (''); ERROR: invalid input syntax for type double precision: "" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (''); ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' '); ERROR: invalid input syntax for type double precision: " " LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' '); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); ERROR: invalid input syntax for type double precision: "xyz" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); ERROR: invalid input syntax for type double precision: "5.0.0" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); ERROR: invalid input syntax for type double precision: "5 . 0" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); ERROR: invalid input syntax for type double precision: "5. 0" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); ERROR: invalid input syntax for type double precision: " - 3" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ERROR: invalid input syntax for type double precision: "123 5" LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); ^ -- special inputs SELECT 'NaN'::float8; float8 -------- NaN (1 row) SELECT 'nan'::float8; float8 -------- NaN (1 row) SELECT ' NAN '::float8; float8 -------- NaN (1 row) SELECT 'infinity'::float8; float8 ---------- Infinity (1 row) SELECT ' -INFINiTY '::float8; float8 ----------- -Infinity (1 row) -- bad special inputs SELECT 'N A N'::float8; ERROR: invalid input syntax for type double precision: "N A N" LINE 1: SELECT 'N A N'::float8; ^ SELECT 'NaN x'::float8; ERROR: invalid input syntax for type double precision: "NaN x" LINE 1: SELECT 'NaN x'::float8; ^ SELECT ' INFINITY x'::float8; ERROR: invalid input syntax for type double precision: " INFINITY x" LINE 1: SELECT ' INFINITY x'::float8; ^ SELECT 'Infinity'::float8 + 100.0; ?column? ---------- Infinity (1 row) SELECT 'Infinity'::float8 / 'Infinity'::float8; ?column? ---------- NaN (1 row) SELECT '42'::float8 / 'Infinity'::float8; ?column? ---------- 0 (1 row) SELECT 'nan'::float8 / 'nan'::float8; ?column? ---------- NaN (1 row) SELECT 'nan'::float8 / '0'::float8; ?column? ---------- NaN (1 row) SELECT 'nan'::numeric::float8; float8 -------- NaN (1 row) SELECT * FROM FLOAT8_TBL; f1 ---------------------- 0 1004.3 -34.84 1.2345678901234e+200 1.2345678901234e-200 (5 rows) SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; f1 ---------------------- 0 -34.84 1.2345678901234e+200 1.2345678901234e-200 (4 rows) SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; f1 -------- 1004.3 (1 row) SELECT f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; f1 ---------------------- 0 -34.84 1.2345678901234e-200 (3 rows) SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; f1 ---------------------- 0 -34.84 1.2345678901234e-200 (3 rows) SELECT f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; f1 ---------------------- 0 1004.3 -34.84 1.2345678901234e-200 (4 rows) SELECT f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; f1 ---------------------- 0 1004.3 -34.84 1.2345678901234e-200 (4 rows) SELECT f.f1, f.f1 * '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; f1 | x ----------------------+----------------------- 1004.3 | -10043 1.2345678901234e+200 | -1.2345678901234e+201 1.2345678901234e-200 | -1.2345678901234e-199 (3 rows) SELECT f.f1, f.f1 + '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; f1 | x ----------------------+---------------------- 1004.3 | 994.3 1.2345678901234e+200 | 1.2345678901234e+200 1.2345678901234e-200 | -10 (3 rows) SELECT f.f1, f.f1 - '-10' AS x FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; f1 | x ----------------------+---------------------- 1004.3 | 1014.3 1.2345678901234e+200 | 1.2345678901234e+200 1.2345678901234e-200 | 10 (3 rows) -- absolute value SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT8_TBL f; f1 | abs_f1 ----------------------+---------------------- 0 | 0 1004.3 | 1004.3 -34.84 | 34.84 1.2345678901234e+200 | 1.2345678901234e+200 1.2345678901234e-200 | 1.2345678901234e-200 (5 rows) -- truncate SELECT f.f1, trunc(f.f1) AS trunc_f1 FROM FLOAT8_TBL f; f1 | trunc_f1 ----------------------+---------------------- 0 | 0 1004.3 | 1004 -34.84 | -34 1.2345678901234e+200 | 1.2345678901234e+200 1.2345678901234e-200 | 0 (5 rows) -- round SELECT f.f1, round(f.f1) AS round_f1 FROM FLOAT8_TBL f; f1 | round_f1 ----------------------+---------------------- 0 | 0 1004.3 | 1004 -34.84 | -35 1.2345678901234e+200 | 1.2345678901234e+200 1.2345678901234e-200 | 0 (5 rows) -- avoid bit-exact output here because operations may not be bit-exact. SET extra_float_digits = 0; -- square root SELECT sqrt(float8 '64') AS eight; eight ------- 8 (1 row) SELECT |/ float8 '64' AS eight; eight ------- 8 (1 row) SELECT f.f1, |/f.f1 AS sqrt_f1 FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; f1 | sqrt_f1 ----------------------+----------------------- 1004.3 | 31.6906926399535 1.2345678901234e+200 | 1.11111110611109e+100 1.2345678901234e-200 | 1.11111110611109e-100 (3 rows) -- power SELECT power(float8 '144', float8 '0.5'); power ------- 12 (1 row) SELECT power(float8 'NaN', float8 '0.5'); power ------- NaN (1 row) SELECT power(float8 '144', float8 'NaN'); power ------- NaN (1 row) SELECT power(float8 'NaN', float8 'NaN'); power ------- NaN (1 row) SELECT power(float8 '-1', float8 'NaN'); power ------- NaN (1 row) SELECT power(float8 '1', float8 'NaN'); power ------- 1 (1 row) SELECT power(float8 'NaN', float8 '0'); power ------- 1 (1 row) SELECT power(float8 'inf', float8 '0'); power ------- 1 (1 row) SELECT power(float8 '-inf', float8 '0'); power ------- 1 (1 row) SELECT power(float8 '0', float8 'inf'); power ------- 0 (1 row) SELECT power(float8 '0', float8 '-inf'); ERROR: zero raised to a negative power is undefined SELECT power(float8 '1', float8 'inf'); power ------- 1 (1 row) SELECT power(float8 '1', float8 '-inf'); power ------- 1 (1 row) SELECT power(float8 '-1', float8 'inf'); power ------- 1 (1 row) SELECT power(float8 '-1', float8 '-inf'); power ------- 1 (1 row) SELECT power(float8 '0.1', float8 'inf'); power ------- 0 (1 row) SELECT power(float8 '-0.1', float8 'inf'); power ------- 0 (1 row) SELECT power(float8 '1.1', float8 'inf'); power ---------- Infinity (1 row) SELECT power(float8 '-1.1', float8 'inf'); power ---------- Infinity (1 row) SELECT power(float8 '0.1', float8 '-inf'); power ---------- Infinity (1 row) SELECT power(float8 '-0.1', float8 '-inf'); power ---------- Infinity (1 row) SELECT power(float8 '1.1', float8 '-inf'); power ------- 0 (1 row) SELECT power(float8 '-1.1', float8 '-inf'); power ------- 0 (1 row) SELECT power(float8 'inf', float8 '-2'); power ------- 0 (1 row) SELECT power(float8 'inf', float8 '2'); power ---------- Infinity (1 row) SELECT power(float8 'inf', float8 'inf'); power ---------- Infinity (1 row) SELECT power(float8 'inf', float8 '-inf'); power ------- 0 (1 row) -- Intel's icc misoptimizes the code that controls the sign of this result, -- even with -mp1. Pending a fix for that, only test for "is it zero". SELECT power(float8 '-inf', float8 '-2') = '0'; ?column? ---------- t (1 row) SELECT power(float8 '-inf', float8 '-3'); power ------- -0 (1 row) SELECT power(float8 '-inf', float8 '2'); power ---------- Infinity (1 row) SELECT power(float8 '-inf', float8 '3'); power ----------- -Infinity (1 row) SELECT power(float8 '-inf', float8 '3.5'); ERROR: a negative number raised to a non-integer power yields a complex result SELECT power(float8 '-inf', float8 'inf'); power ---------- Infinity (1 row) SELECT power(float8 '-inf', float8 '-inf'); power ------- 0 (1 row) -- take exp of ln(f.f1) SELECT f.f1, exp(ln(f.f1)) AS exp_ln_f1 FROM FLOAT8_TBL f WHERE f.f1 > '0.0'; f1 | exp_ln_f1 ----------------------+----------------------- 1004.3 | 1004.3 1.2345678901234e+200 | 1.23456789012338e+200 1.2345678901234e-200 | 1.23456789012339e-200 (3 rows) -- cube root SELECT ||/ float8 '27' AS three; three ------- 3 (1 row) SELECT f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; f1 | cbrt_f1 ----------------------+---------------------- 0 | 0 1004.3 | 10.014312837827 -34.84 | -3.26607421344208 1.2345678901234e+200 | 4.97933859234765e+66 1.2345678901234e-200 | 2.3112042409018e-67 (5 rows) SELECT * FROM FLOAT8_TBL; f1 ---------------------- 0 1004.3 -34.84 1.2345678901234e+200 1.2345678901234e-200 (5 rows) SELECT f.f1 * '1e200' from FLOAT8_TBL f; ERROR: value out of range: overflow SELECT f.f1 ^ '1e200' from FLOAT8_TBL f; ERROR: value out of range: overflow SELECT 0 ^ 0 + 0 ^ 1 + 0 ^ 0.0 + 0 ^ 0.5; ?column? ---------- 2 (1 row) SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; ERROR: cannot take logarithm of zero SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; ERROR: cannot take logarithm of a negative number SELECT f.f1 / '0.0' from FLOAT8_TBL f; ERROR: division by zero -- hyperbolic functions -- we run these with extra_float_digits = 0 too, since different platforms -- tend to produce results that vary in the last place. SELECT sinh(float8 '1'); sinh ----------------- 1.1752011936438 (1 row) SELECT cosh(float8 '1'); cosh ------------------ 1.54308063481524 (1 row) SELECT tanh(float8 '1'); tanh ------------------- 0.761594155955765 (1 row) SELECT asinh(float8 '1'); asinh ------------------- 0.881373587019543 (1 row) SELECT acosh(float8 '2'); acosh ------------------ 1.31695789692482 (1 row) SELECT atanh(float8 '0.5'); atanh ------------------- 0.549306144334055 (1 row) -- test Inf/NaN cases for hyperbolic functions SELECT sinh(float8 'infinity'); sinh ---------- Infinity (1 row) SELECT sinh(float8 '-infinity'); sinh ----------- -Infinity (1 row) SELECT sinh(float8 'nan'); sinh ------ NaN (1 row) SELECT cosh(float8 'infinity'); cosh ---------- Infinity (1 row) SELECT cosh(float8 '-infinity'); cosh ---------- Infinity (1 row) SELECT cosh(float8 'nan'); cosh ------ NaN (1 row) SELECT tanh(float8 'infinity'); tanh ------ 1 (1 row) SELECT tanh(float8 '-infinity'); tanh ------ -1 (1 row) SELECT tanh(float8 'nan'); tanh ------ NaN (1 row) SELECT asinh(float8 'infinity'); asinh ---------- Infinity (1 row) SELECT asinh(float8 '-infinity'); asinh ----------- -Infinity (1 row) SELECT asinh(float8 'nan'); asinh ------- NaN (1 row) -- acosh(Inf) should be Inf, but some mingw versions produce NaN, so skip test -- SELECT acosh(float8 'infinity'); SELECT acosh(float8 '-infinity'); ERROR: input is out of range SELECT acosh(float8 'nan'); acosh ------- NaN (1 row) SELECT atanh(float8 'infinity'); ERROR: input is out of range SELECT atanh(float8 '-infinity'); ERROR: input is out of range SELECT atanh(float8 'nan'); atanh ------- NaN (1 row) RESET extra_float_digits; -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); ERROR: "10e400" is out of range for type double precision LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); ERROR: "-10e400" is out of range for type double precision LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); ERROR: "10e-400" is out of range for type double precision LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); ERROR: "-10e-400" is out of range for type double precision LINE 1: INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); ^ INSERT INTO FLOAT8_TBL(f1) VALUES ('0.0'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-34.84'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-1004.30'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e+200'); INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e-200'); -- test edge-case coercions to integer SELECT '32767.4'::float8::int2; int2 ------- 32767 (1 row) SELECT '32767.6'::float8::int2; ERROR: smallint out of range SELECT '-32768.4'::float8::int2; int2 -------- -32768 (1 row) SELECT '-32768.6'::float8::int2; ERROR: smallint out of range SELECT '2147483647.4'::float8::int4; int4 ------------ 2147483647 (1 row) SELECT '2147483647.6'::float8::int4; ERROR: integer out of range SELECT '-2147483648.4'::float8::int4; int4 ------------- -2147483648 (1 row) SELECT '-2147483648.6'::float8::int4; ERROR: integer out of range SELECT '9223372036854773760'::float8::int8; int8 --------------------- 9223372036854773760 (1 row) SELECT '9223372036854775807'::float8::int8; ERROR: bigint out of range SELECT '-9223372036854775808.5'::float8::int8; int8 ---------------------- -9223372036854775808 (1 row) SELECT '-9223372036854780000'::float8::int8; ERROR: bigint out of range -- test exact cases for trigonometric functions in degrees SELECT x, sind(x), sind(x) IN (-1,-0.5,0,0.5,1) AS sind_exact FROM (VALUES (0), (30), (90), (150), (180), (210), (270), (330), (360)) AS t(x); x | sind | sind_exact -----+------+------------ 0 | 0 | t 30 | 0.5 | t 90 | 1 | t 150 | 0.5 | t 180 | 0 | t 210 | -0.5 | t 270 | -1 | t 330 | -0.5 | t 360 | 0 | t (9 rows) SELECT x, cosd(x), cosd(x) IN (-1,-0.5,0,0.5,1) AS cosd_exact FROM (VALUES (0), (60), (90), (120), (180), (240), (270), (300), (360)) AS t(x); x | cosd | cosd_exact -----+------+------------ 0 | 1 | t 60 | 0.5 | t 90 | 0 | t 120 | -0.5 | t 180 | -1 | t 240 | -0.5 | t 270 | 0 | t 300 | 0.5 | t 360 | 1 | t (9 rows) SELECT x, tand(x), tand(x) IN ('-Infinity'::float8,-1,0, 1,'Infinity'::float8) AS tand_exact, cotd(x), cotd(x) IN ('-Infinity'::float8,-1,0, 1,'Infinity'::float8) AS cotd_exact FROM (VALUES (0), (45), (90), (135), (180), (225), (270), (315), (360)) AS t(x); x | tand | tand_exact | cotd | cotd_exact -----+-----------+------------+-----------+------------ 0 | 0 | t | Infinity | t 45 | 1 | t | 1 | t 90 | Infinity | t | 0 | t 135 | -1 | t | -1 | t 180 | 0 | t | -Infinity | t 225 | 1 | t | 1 | t 270 | -Infinity | t | 0 | t 315 | -1 | t | -1 | t 360 | 0 | t | Infinity | t (9 rows) SELECT x, atand(x), atand(x) IN (-90,-45,0,45,90) AS atand_exact FROM (VALUES ('-Infinity'::float8), (-1), (0), (1), ('Infinity'::float8)) AS t(x); x | atand | atand_exact -----------+-------+------------- -Infinity | -90 | t -1 | -45 | t 0 | 0 | t 1 | 45 | t Infinity | 90 | t (5 rows) SELECT x, y, atan2d(y, x), atan2d(y, x) IN (-90,0,90,180) AS atan2d_exact FROM (SELECT 10*cosd(a), 10*sind(a) FROM generate_series(0, 360, 90) AS t(a)) AS t(x,y); x | y | atan2d | atan2d_exact -----+-----+--------+-------------- 10 | 0 | 0 | t 0 | 10 | 90 | t -10 | 0 | 180 | t 0 | -10 | -90 | t 10 | 0 | 0 | t (5 rows)