1
/*-------------------------------------------------------------------------
4
* Functions for the built-in floating-point types.
6
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.112 2004-12-31 22:01:21 pgsql Exp $
13
*-------------------------------------------------------------------------
18
* float4in, float4out, float4recv, float4send
19
* float4abs, float4um, float4up
21
* float8in, float8out, float8recv, float8send
22
* float8abs, float8um, float8up
23
* Arithmetic operators:
24
* float4pl, float4mi, float4mul, float4div
25
* float8pl, float8mi, float8mul, float8div
26
* Comparison operators:
27
* float4eq, float4ne, float4lt, float4le, float4gt, float4ge, float4cmp
28
* float8eq, float8ne, float8lt, float8le, float8gt, float8ge, float8cmp
29
* Conversion routines:
30
* ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
33
* dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
34
* Arithmetic operators:
35
* float48pl, float48mi, float48mul, float48div
36
* float84pl, float84mi, float84mul, float84div
37
* Comparison operators:
38
* float48eq, float48ne, float48lt, float48le, float48gt, float48ge
39
* float84eq, float84ne, float84lt, float84le, float84gt, float84ge
41
* (You can do the arithmetic and comparison stuff using conversion
42
* routines, but then you pay the overhead of invoking a separate
43
* conversion function...)
45
* XXX GLUESOME STUFF. FIX IT! -AY '94
47
* Added some additional conversion routines and cleaned up
48
* a bit of the existing code. Need to change the error checking
49
* for calls to pow(), exp() since on some machines (my Linux box
50
* included) these routines do not set errno. - tgl 97/05/10
60
/* for finite() on Solaris */
65
#include "catalog/pg_type.h"
67
#include "libpq/pqformat.h"
68
#include "utils/array.h"
69
#include "utils/builtins.h"
73
/* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
74
#define M_PI 3.14159265358979323846
78
#define SHRT_MAX 32767
81
#define SHRT_MIN (-32768)
84
/* Recent HPUXen have isfinite() macro in place of more standard finite() */
85
#if !defined(HAVE_FINITE) && defined(isfinite)
86
#define finite(x) isfinite(x)
90
/* not sure what the following should be, but better to make it over-sufficient */
91
#define MAXFLOATWIDTH 64
92
#define MAXDOUBLEWIDTH 128
94
/* ========== USER I/O ROUTINES ========== */
97
#define FLOAT4_MAX FLT_MAX
98
#define FLOAT4_MIN FLT_MIN
99
#define FLOAT8_MAX DBL_MAX
100
#define FLOAT8_MIN DBL_MIN
103
/* Configurable GUC parameter */
104
int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
107
static void CheckFloat4Val(double val);
108
static void CheckFloat8Val(double val);
109
static int float4_cmp_internal(float4 a, float4 b);
110
static int float8_cmp_internal(float8 a, float8 b);
113
static double cbrt(double x);
114
#endif /* HAVE_CBRT */
118
* Routines to provide reasonably platform-independent handling of
119
* infinity and NaN. We assume that isinf() and isnan() are available
120
* and work per spec. (On some platforms, we have to supply our own;
121
* see src/port.) However, generating an Infinity or NaN in the first
122
* place is less well standardized; pre-C99 systems tend not to have C99's
123
* INFINITY and NAN macros. We centralize our workarounds for this here.
127
get_float8_infinity(void)
130
/* C99 standard way */
131
return (double) INFINITY;
135
* On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
136
* largest normal double. We assume forcing an overflow will get us a
139
return (double) (HUGE_VAL * HUGE_VAL);
144
get_float4_infinity(void)
147
/* C99 standard way */
148
return (float) INFINITY;
152
* On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
153
* largest normal double. We assume forcing an overflow will get us a
156
return (float) (HUGE_VAL * HUGE_VAL);
164
/* C99 standard way */
167
/* Assume we can get a NAN via zero divide */
168
return (double) (0.0 / 0.0);
176
/* C99 standard way */
179
/* Assume we can get a NAN via zero divide */
180
return (float) (0.0 / 0.0);
186
* Returns -1 if 'val' represents negative infinity, 1 if 'val'
187
* represents (positive) infinity, and 0 otherwise. On some platforms,
188
* this is equivalent to the isinf() macro, but not everywhere: C99
189
* does not specify that isinf() needs to distinguish between positive
190
* and negative infinity.
193
is_infinite(double val)
195
int inf = isinf(val);
208
* check to see if a float4 val is outside of the FLOAT4_MIN,
211
* raise an ereport() error if it is
214
CheckFloat4Val(double val)
216
if (fabs(val) > FLOAT4_MAX)
218
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
219
errmsg("type \"real\" value out of range: overflow")));
220
if (val != 0.0 && fabs(val) < FLOAT4_MIN)
222
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
223
errmsg("type \"real\" value out of range: underflow")));
227
* check to see if a float8 val is outside of the FLOAT8_MIN,
230
* raise an ereport() error if it is
233
CheckFloat8Val(double val)
235
if (fabs(val) > FLOAT8_MAX)
237
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
238
errmsg("type \"double precision\" value out of range: overflow")));
239
if (val != 0.0 && fabs(val) < FLOAT8_MIN)
241
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
242
errmsg("type \"double precision\" value out of range: underflow")));
246
* float4in - converts "num" to float
248
* {<sp>} [+|-] {digit} [.{digit}] [<exp>]
249
* where <sp> is a space, digit is 0-9,
250
* <exp> is "e" or "E" followed by an integer.
253
float4in(PG_FUNCTION_ARGS)
255
char *num = PG_GETARG_CSTRING(0);
261
* endptr points to the first character _after_ the sequence we
262
* recognized as a valid floating point number. orig_num points to the
263
* original input string.
268
* Check for an empty-string input to begin with, to avoid the
269
* vagaries of strtod() on different platforms.
271
* In releases prior to 8.0, we accepted an empty string as valid input
272
* (yielding a float4 of 0). In 8.0, we accept empty strings, but emit
273
* a warning noting that the feature is deprecated. In 8.1+, the
274
* warning should be replaced by an error.
279
(errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
280
errmsg("deprecated input syntax for type real: \"\""),
281
errdetail("This input will be rejected in "
282
"a future release of PostgreSQL.")));
283
PG_RETURN_FLOAT4((float4) 0.0);
286
/* skip leading whitespace */
287
while (*num != '\0' && isspace((unsigned char) *num))
291
val = strtod(num, &endptr);
293
/* did we not see anything that looks like a double? */
294
if (endptr == num || errno != 0)
297
* C99 requires that strtod() accept NaN and [-]Infinity, but not
298
* all platforms support that yet (and some accept them but set
299
* ERANGE anyway...) Therefore, we check for these inputs
302
if (pg_strncasecmp(num, "NaN", 3) == 0)
304
val = get_float4_nan();
307
else if (pg_strncasecmp(num, "Infinity", 8) == 0)
309
val = get_float4_infinity();
312
else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
314
val = -get_float4_infinity();
317
else if (errno == ERANGE)
319
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
320
errmsg("\"%s\" is out of range for type real",
324
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
325
errmsg("invalid input syntax for type real: \"%s\"",
328
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
332
* Many versions of Solaris have a bug wherein strtod sets endptr
333
* to point one byte beyond the end of the string when given "inf"
336
if (endptr != num && endptr[-1] == '\0')
339
#endif /* HAVE_BUGGY_SOLARIS_STRTOD */
341
/* skip trailing whitespace */
342
while (*endptr != '\0' && isspace((unsigned char) *endptr))
345
/* if there is any junk left at the end of the string, bail out */
348
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
349
errmsg("invalid input syntax for type real: \"%s\"",
353
* if we get here, we have a legal double, still need to check to see
354
* if it's a legal float4
359
PG_RETURN_FLOAT4((float4) val);
363
* float4out - converts a float4 number to a string
364
* using a standard output format
367
float4out(PG_FUNCTION_ARGS)
369
float4 num = PG_GETARG_FLOAT4(0);
370
char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
373
PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
375
switch (is_infinite(num))
378
strcpy(ascii, "Infinity");
381
strcpy(ascii, "-Infinity");
385
int ndig = FLT_DIG + extra_float_digits;
390
sprintf(ascii, "%.*g", ndig, num);
394
PG_RETURN_CSTRING(ascii);
398
* float4recv - converts external binary format to float4
401
float4recv(PG_FUNCTION_ARGS)
403
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
405
PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));
409
* float4send - converts float4 to binary format
412
float4send(PG_FUNCTION_ARGS)
414
float4 num = PG_GETARG_FLOAT4(0);
417
pq_begintypsend(&buf);
418
pq_sendfloat4(&buf, num);
419
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
423
* float8in - converts "num" to float8
425
* {<sp>} [+|-] {digit} [.{digit}] [<exp>]
426
* where <sp> is a space, digit is 0-9,
427
* <exp> is "e" or "E" followed by an integer.
430
float8in(PG_FUNCTION_ARGS)
432
char *num = PG_GETARG_CSTRING(0);
438
* endptr points to the first character _after_ the sequence we
439
* recognized as a valid floating point number. orig_num points to the
440
* original input string.
445
* Check for an empty-string input to begin with, to avoid the
446
* vagaries of strtod() on different platforms.
448
* In releases prior to 8.0, we accepted an empty string as valid input
449
* (yielding a float8 of 0). In 8.0, we accept empty strings, but emit
450
* a warning noting that the feature is deprecated. In 8.1+, the
451
* warning should be replaced by an error.
456
(errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
457
errmsg("deprecated input syntax for type double precision: \"\""),
458
errdetail("This input will be rejected in "
459
"a future release of PostgreSQL.")));
460
PG_RETURN_FLOAT8(0.0);
463
/* skip leading whitespace */
464
while (*num != '\0' && isspace((unsigned char) *num))
468
val = strtod(num, &endptr);
470
/* did we not see anything that looks like a double? */
471
if (endptr == num || errno != 0)
474
* C99 requires that strtod() accept NaN and [-]Infinity, but not
475
* all platforms support that yet (and some accept them but set
476
* ERANGE anyway...) Therefore, we check for these inputs
479
if (pg_strncasecmp(num, "NaN", 3) == 0)
481
val = get_float8_nan();
484
else if (pg_strncasecmp(num, "Infinity", 8) == 0)
486
val = get_float8_infinity();
489
else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
491
val = -get_float8_infinity();
494
else if (errno == ERANGE)
496
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
497
errmsg("\"%s\" is out of range for type double precision",
501
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
502
errmsg("invalid input syntax for type double precision: \"%s\"",
505
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
509
* Many versions of Solaris have a bug wherein strtod sets endptr
510
* to point one byte beyond the end of the string when given "inf"
513
if (endptr != num && endptr[-1] == '\0')
516
#endif /* HAVE_BUGGY_SOLARIS_STRTOD */
518
/* skip trailing whitespace */
519
while (*endptr != '\0' && isspace((unsigned char) *endptr))
522
/* if there is any junk left at the end of the string, bail out */
525
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
526
errmsg("invalid input syntax for type double precision: \"%s\"",
532
PG_RETURN_FLOAT8(val);
536
* float8out - converts float8 number to a string
537
* using a standard output format
540
float8out(PG_FUNCTION_ARGS)
542
float8 num = PG_GETARG_FLOAT8(0);
543
char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
546
PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
548
switch (is_infinite(num))
551
strcpy(ascii, "Infinity");
554
strcpy(ascii, "-Infinity");
558
int ndig = DBL_DIG + extra_float_digits;
563
sprintf(ascii, "%.*g", ndig, num);
567
PG_RETURN_CSTRING(ascii);
571
* float8recv - converts external binary format to float8
574
float8recv(PG_FUNCTION_ARGS)
576
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
578
PG_RETURN_FLOAT8(pq_getmsgfloat8(buf));
582
* float8send - converts float8 to binary format
585
float8send(PG_FUNCTION_ARGS)
587
float8 num = PG_GETARG_FLOAT8(0);
590
pq_begintypsend(&buf);
591
pq_sendfloat8(&buf, num);
592
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
596
/* ========== PUBLIC ROUTINES ========== */
600
* ======================
601
* FLOAT4 BASE OPERATIONS
602
* ======================
606
* float4abs - returns |arg1| (absolute value)
609
float4abs(PG_FUNCTION_ARGS)
611
float4 arg1 = PG_GETARG_FLOAT4(0);
613
PG_RETURN_FLOAT4((float4) fabs(arg1));
617
* float4um - returns -arg1 (unary minus)
620
float4um(PG_FUNCTION_ARGS)
622
float4 arg1 = PG_GETARG_FLOAT4(0);
624
PG_RETURN_FLOAT4((float4) -arg1);
628
float4up(PG_FUNCTION_ARGS)
630
float4 arg = PG_GETARG_FLOAT4(0);
632
PG_RETURN_FLOAT4(arg);
636
float4larger(PG_FUNCTION_ARGS)
638
float4 arg1 = PG_GETARG_FLOAT4(0);
639
float4 arg2 = PG_GETARG_FLOAT4(1);
642
if (float4_cmp_internal(arg1, arg2) > 0)
646
PG_RETURN_FLOAT4(result);
650
float4smaller(PG_FUNCTION_ARGS)
652
float4 arg1 = PG_GETARG_FLOAT4(0);
653
float4 arg2 = PG_GETARG_FLOAT4(1);
656
if (float4_cmp_internal(arg1, arg2) < 0)
660
PG_RETURN_FLOAT4(result);
664
* ======================
665
* FLOAT8 BASE OPERATIONS
666
* ======================
670
* float8abs - returns |arg1| (absolute value)
673
float8abs(PG_FUNCTION_ARGS)
675
float8 arg1 = PG_GETARG_FLOAT8(0);
680
CheckFloat8Val(result);
681
PG_RETURN_FLOAT8(result);
686
* float8um - returns -arg1 (unary minus)
689
float8um(PG_FUNCTION_ARGS)
691
float8 arg1 = PG_GETARG_FLOAT8(0);
694
result = ((arg1 != 0) ? -(arg1) : arg1);
696
CheckFloat8Val(result);
697
PG_RETURN_FLOAT8(result);
701
float8up(PG_FUNCTION_ARGS)
703
float8 arg = PG_GETARG_FLOAT8(0);
705
PG_RETURN_FLOAT8(arg);
709
float8larger(PG_FUNCTION_ARGS)
711
float8 arg1 = PG_GETARG_FLOAT8(0);
712
float8 arg2 = PG_GETARG_FLOAT8(1);
715
if (float8_cmp_internal(arg1, arg2) > 0)
719
PG_RETURN_FLOAT8(result);
723
float8smaller(PG_FUNCTION_ARGS)
725
float8 arg1 = PG_GETARG_FLOAT8(0);
726
float8 arg2 = PG_GETARG_FLOAT8(1);
729
if (float8_cmp_internal(arg1, arg2) < 0)
733
PG_RETURN_FLOAT8(result);
738
* ====================
739
* ARITHMETIC OPERATORS
740
* ====================
744
* float4pl - returns arg1 + arg2
745
* float4mi - returns arg1 - arg2
746
* float4mul - returns arg1 * arg2
747
* float4div - returns arg1 / arg2
750
float4pl(PG_FUNCTION_ARGS)
752
float4 arg1 = PG_GETARG_FLOAT4(0);
753
float4 arg2 = PG_GETARG_FLOAT4(1);
756
result = arg1 + arg2;
757
CheckFloat4Val(result);
758
PG_RETURN_FLOAT4((float4) result);
762
float4mi(PG_FUNCTION_ARGS)
764
float4 arg1 = PG_GETARG_FLOAT4(0);
765
float4 arg2 = PG_GETARG_FLOAT4(1);
768
result = arg1 - arg2;
769
CheckFloat4Val(result);
770
PG_RETURN_FLOAT4((float4) result);
774
float4mul(PG_FUNCTION_ARGS)
776
float4 arg1 = PG_GETARG_FLOAT4(0);
777
float4 arg2 = PG_GETARG_FLOAT4(1);
780
result = arg1 * arg2;
781
CheckFloat4Val(result);
782
PG_RETURN_FLOAT4((float4) result);
786
float4div(PG_FUNCTION_ARGS)
788
float4 arg1 = PG_GETARG_FLOAT4(0);
789
float4 arg2 = PG_GETARG_FLOAT4(1);
794
(errcode(ERRCODE_DIVISION_BY_ZERO),
795
errmsg("division by zero")));
797
/* Do division in float8, then check for overflow */
798
result = (float8) arg1 / (float8) arg2;
800
CheckFloat4Val(result);
801
PG_RETURN_FLOAT4((float4) result);
805
* float8pl - returns arg1 + arg2
806
* float8mi - returns arg1 - arg2
807
* float8mul - returns arg1 * arg2
808
* float8div - returns arg1 / arg2
811
float8pl(PG_FUNCTION_ARGS)
813
float8 arg1 = PG_GETARG_FLOAT8(0);
814
float8 arg2 = PG_GETARG_FLOAT8(1);
817
result = arg1 + arg2;
819
CheckFloat8Val(result);
820
PG_RETURN_FLOAT8(result);
824
float8mi(PG_FUNCTION_ARGS)
826
float8 arg1 = PG_GETARG_FLOAT8(0);
827
float8 arg2 = PG_GETARG_FLOAT8(1);
830
result = arg1 - arg2;
832
CheckFloat8Val(result);
833
PG_RETURN_FLOAT8(result);
837
float8mul(PG_FUNCTION_ARGS)
839
float8 arg1 = PG_GETARG_FLOAT8(0);
840
float8 arg2 = PG_GETARG_FLOAT8(1);
843
result = arg1 * arg2;
845
CheckFloat8Val(result);
846
PG_RETURN_FLOAT8(result);
850
float8div(PG_FUNCTION_ARGS)
852
float8 arg1 = PG_GETARG_FLOAT8(0);
853
float8 arg2 = PG_GETARG_FLOAT8(1);
858
(errcode(ERRCODE_DIVISION_BY_ZERO),
859
errmsg("division by zero")));
861
result = arg1 / arg2;
863
CheckFloat8Val(result);
864
PG_RETURN_FLOAT8(result);
869
* ====================
870
* COMPARISON OPERATORS
871
* ====================
875
* float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
878
float4_cmp_internal(float4 a, float4 b)
881
* We consider all NANs to be equal and larger than any non-NAN. This
882
* is somewhat arbitrary; the important thing is to have a consistent
888
return 0; /* NAN = NAN */
890
return 1; /* NAN > non-NAN */
894
return -1; /* non-NAN < NAN */
908
float4eq(PG_FUNCTION_ARGS)
910
float4 arg1 = PG_GETARG_FLOAT4(0);
911
float4 arg2 = PG_GETARG_FLOAT4(1);
913
PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);
917
float4ne(PG_FUNCTION_ARGS)
919
float4 arg1 = PG_GETARG_FLOAT4(0);
920
float4 arg2 = PG_GETARG_FLOAT4(1);
922
PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);
926
float4lt(PG_FUNCTION_ARGS)
928
float4 arg1 = PG_GETARG_FLOAT4(0);
929
float4 arg2 = PG_GETARG_FLOAT4(1);
931
PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);
935
float4le(PG_FUNCTION_ARGS)
937
float4 arg1 = PG_GETARG_FLOAT4(0);
938
float4 arg2 = PG_GETARG_FLOAT4(1);
940
PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);
944
float4gt(PG_FUNCTION_ARGS)
946
float4 arg1 = PG_GETARG_FLOAT4(0);
947
float4 arg2 = PG_GETARG_FLOAT4(1);
949
PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);
953
float4ge(PG_FUNCTION_ARGS)
955
float4 arg1 = PG_GETARG_FLOAT4(0);
956
float4 arg2 = PG_GETARG_FLOAT4(1);
958
PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);
962
btfloat4cmp(PG_FUNCTION_ARGS)
964
float4 arg1 = PG_GETARG_FLOAT4(0);
965
float4 arg2 = PG_GETARG_FLOAT4(1);
967
PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
971
* float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
974
float8_cmp_internal(float8 a, float8 b)
977
* We consider all NANs to be equal and larger than any non-NAN. This
978
* is somewhat arbitrary; the important thing is to have a consistent
984
return 0; /* NAN = NAN */
986
return 1; /* NAN > non-NAN */
990
return -1; /* non-NAN < NAN */
1004
float8eq(PG_FUNCTION_ARGS)
1006
float8 arg1 = PG_GETARG_FLOAT8(0);
1007
float8 arg2 = PG_GETARG_FLOAT8(1);
1009
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
1013
float8ne(PG_FUNCTION_ARGS)
1015
float8 arg1 = PG_GETARG_FLOAT8(0);
1016
float8 arg2 = PG_GETARG_FLOAT8(1);
1018
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
1022
float8lt(PG_FUNCTION_ARGS)
1024
float8 arg1 = PG_GETARG_FLOAT8(0);
1025
float8 arg2 = PG_GETARG_FLOAT8(1);
1027
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
1031
float8le(PG_FUNCTION_ARGS)
1033
float8 arg1 = PG_GETARG_FLOAT8(0);
1034
float8 arg2 = PG_GETARG_FLOAT8(1);
1036
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
1040
float8gt(PG_FUNCTION_ARGS)
1042
float8 arg1 = PG_GETARG_FLOAT8(0);
1043
float8 arg2 = PG_GETARG_FLOAT8(1);
1045
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
1049
float8ge(PG_FUNCTION_ARGS)
1051
float8 arg1 = PG_GETARG_FLOAT8(0);
1052
float8 arg2 = PG_GETARG_FLOAT8(1);
1054
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
1058
btfloat8cmp(PG_FUNCTION_ARGS)
1060
float8 arg1 = PG_GETARG_FLOAT8(0);
1061
float8 arg2 = PG_GETARG_FLOAT8(1);
1063
PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1067
btfloat48cmp(PG_FUNCTION_ARGS)
1069
float4 arg1 = PG_GETARG_FLOAT4(0);
1070
float8 arg2 = PG_GETARG_FLOAT8(1);
1072
/* widen float4 to float8 and then compare */
1073
PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1077
btfloat84cmp(PG_FUNCTION_ARGS)
1079
float8 arg1 = PG_GETARG_FLOAT8(0);
1080
float4 arg2 = PG_GETARG_FLOAT4(1);
1082
/* widen float4 to float8 and then compare */
1083
PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
1088
* ===================
1089
* CONVERSION ROUTINES
1090
* ===================
1094
* ftod - converts a float4 number to a float8 number
1097
ftod(PG_FUNCTION_ARGS)
1099
float4 num = PG_GETARG_FLOAT4(0);
1101
PG_RETURN_FLOAT8((float8) num);
1106
* dtof - converts a float8 number to a float4 number
1109
dtof(PG_FUNCTION_ARGS)
1111
float8 num = PG_GETARG_FLOAT8(0);
1113
CheckFloat4Val(num);
1115
PG_RETURN_FLOAT4((float4) num);
1120
* dtoi4 - converts a float8 number to an int4 number
1123
dtoi4(PG_FUNCTION_ARGS)
1125
float8 num = PG_GETARG_FLOAT8(0);
1128
if ((num < INT_MIN) || (num > INT_MAX))
1130
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1131
errmsg("integer out of range")));
1133
result = (int32) rint(num);
1134
PG_RETURN_INT32(result);
1139
* dtoi2 - converts a float8 number to an int2 number
1142
dtoi2(PG_FUNCTION_ARGS)
1144
float8 num = PG_GETARG_FLOAT8(0);
1147
if ((num < SHRT_MIN) || (num > SHRT_MAX))
1149
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1150
errmsg("smallint out of range")));
1152
result = (int16) rint(num);
1153
PG_RETURN_INT16(result);
1158
* i4tod - converts an int4 number to a float8 number
1161
i4tod(PG_FUNCTION_ARGS)
1163
int32 num = PG_GETARG_INT32(0);
1167
PG_RETURN_FLOAT8(result);
1172
* i2tod - converts an int2 number to a float8 number
1175
i2tod(PG_FUNCTION_ARGS)
1177
int16 num = PG_GETARG_INT16(0);
1181
PG_RETURN_FLOAT8(result);
1186
* ftoi4 - converts a float4 number to an int4 number
1189
ftoi4(PG_FUNCTION_ARGS)
1191
float4 num = PG_GETARG_FLOAT4(0);
1194
if ((num < INT_MIN) || (num > INT_MAX))
1196
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1197
errmsg("integer out of range")));
1199
result = (int32) rint(num);
1200
PG_RETURN_INT32(result);
1205
* ftoi2 - converts a float4 number to an int2 number
1208
ftoi2(PG_FUNCTION_ARGS)
1210
float4 num = PG_GETARG_FLOAT4(0);
1213
if ((num < SHRT_MIN) || (num > SHRT_MAX))
1215
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1216
errmsg("smallint out of range")));
1218
result = (int16) rint(num);
1219
PG_RETURN_INT16(result);
1224
* i4tof - converts an int4 number to a float8 number
1227
i4tof(PG_FUNCTION_ARGS)
1229
int32 num = PG_GETARG_INT32(0);
1233
PG_RETURN_FLOAT4(result);
1238
* i2tof - converts an int2 number to a float4 number
1241
i2tof(PG_FUNCTION_ARGS)
1243
int16 num = PG_GETARG_INT16(0);
1247
PG_RETURN_FLOAT4(result);
1252
* float8_text - converts a float8 number to a text string
1255
float8_text(PG_FUNCTION_ARGS)
1257
float8 num = PG_GETARG_FLOAT8(0);
1262
str = DatumGetCString(DirectFunctionCall1(float8out,
1263
Float8GetDatum(num)));
1265
len = strlen(str) + VARHDRSZ;
1267
result = (text *) palloc(len);
1269
VARATT_SIZEP(result) = len;
1270
memcpy(VARDATA(result), str, (len - VARHDRSZ));
1274
PG_RETURN_TEXT_P(result);
1279
* text_float8 - converts a text string to a float8 number
1282
text_float8(PG_FUNCTION_ARGS)
1284
text *string = PG_GETARG_TEXT_P(0);
1289
len = (VARSIZE(string) - VARHDRSZ);
1290
str = palloc(len + 1);
1291
memcpy(str, VARDATA(string), len);
1292
*(str + len) = '\0';
1294
result = DirectFunctionCall1(float8in, CStringGetDatum(str));
1298
PG_RETURN_DATUM(result);
1303
* float4_text - converts a float4 number to a text string
1306
float4_text(PG_FUNCTION_ARGS)
1308
float4 num = PG_GETARG_FLOAT4(0);
1313
str = DatumGetCString(DirectFunctionCall1(float4out,
1314
Float4GetDatum(num)));
1316
len = strlen(str) + VARHDRSZ;
1318
result = (text *) palloc(len);
1320
VARATT_SIZEP(result) = len;
1321
memcpy(VARDATA(result), str, (len - VARHDRSZ));
1325
PG_RETURN_TEXT_P(result);
1330
* text_float4 - converts a text string to a float4 number
1333
text_float4(PG_FUNCTION_ARGS)
1335
text *string = PG_GETARG_TEXT_P(0);
1340
len = (VARSIZE(string) - VARHDRSZ);
1341
str = palloc(len + 1);
1342
memcpy(str, VARDATA(string), len);
1343
*(str + len) = '\0';
1345
result = DirectFunctionCall1(float4in, CStringGetDatum(str));
1349
PG_RETURN_DATUM(result);
1354
* =======================
1355
* RANDOM FLOAT8 OPERATORS
1356
* =======================
1360
* dround - returns ROUND(arg1)
1363
dround(PG_FUNCTION_ARGS)
1365
float8 arg1 = PG_GETARG_FLOAT8(0);
1368
result = rint(arg1);
1370
PG_RETURN_FLOAT8(result);
1374
* dceil - returns the smallest integer greater than or
1375
* equal to the specified float
1378
dceil(PG_FUNCTION_ARGS)
1380
float8 arg1 = PG_GETARG_FLOAT8(0);
1382
PG_RETURN_FLOAT8(ceil(arg1));
1386
* dfloor - returns the largest integer lesser than or
1387
* equal to the specified float
1390
dfloor(PG_FUNCTION_ARGS)
1392
float8 arg1 = PG_GETARG_FLOAT8(0);
1394
PG_RETURN_FLOAT8(floor(arg1));
1398
* dsign - returns -1 if the argument is less than 0, 0
1399
* if the argument is equal to 0, and 1 if the
1400
* argument is greater than zero.
1403
dsign(PG_FUNCTION_ARGS)
1405
float8 arg1 = PG_GETARG_FLOAT8(0);
1415
PG_RETURN_FLOAT8(result);
1419
* dtrunc - returns truncation-towards-zero of arg1,
1420
* arg1 >= 0 ... the greatest integer less
1421
* than or equal to arg1
1422
* arg1 < 0 ... the least integer greater
1423
* than or equal to arg1
1426
dtrunc(PG_FUNCTION_ARGS)
1428
float8 arg1 = PG_GETARG_FLOAT8(0);
1432
result = floor(arg1);
1434
result = -floor(-arg1);
1436
PG_RETURN_FLOAT8(result);
1441
* dsqrt - returns square root of arg1
1444
dsqrt(PG_FUNCTION_ARGS)
1446
float8 arg1 = PG_GETARG_FLOAT8(0);
1451
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1452
errmsg("cannot take square root of a negative number")));
1454
result = sqrt(arg1);
1456
CheckFloat8Val(result);
1457
PG_RETURN_FLOAT8(result);
1462
* dcbrt - returns cube root of arg1
1465
dcbrt(PG_FUNCTION_ARGS)
1467
float8 arg1 = PG_GETARG_FLOAT8(0);
1470
result = cbrt(arg1);
1471
PG_RETURN_FLOAT8(result);
1476
* dpow - returns pow(arg1,arg2)
1479
dpow(PG_FUNCTION_ARGS)
1481
float8 arg1 = PG_GETARG_FLOAT8(0);
1482
float8 arg2 = PG_GETARG_FLOAT8(1);
1486
* The SQL spec requires that we emit a particular SQLSTATE error code
1487
* for certain error conditions.
1489
if ((arg1 == 0 && arg2 < 0) ||
1490
(arg1 < 0 && floor(arg2) != arg2))
1492
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1493
errmsg("invalid argument for power function")));
1496
* We must check both for errno getting set and for a NaN result, in
1497
* order to deal with the vagaries of different platforms...
1500
result = pow(arg1, arg2);
1507
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1508
errmsg("result is out of range")));
1510
CheckFloat8Val(result);
1511
PG_RETURN_FLOAT8(result);
1516
* dexp - returns the exponential function of arg1
1519
dexp(PG_FUNCTION_ARGS)
1521
float8 arg1 = PG_GETARG_FLOAT8(0);
1525
* We must check both for errno getting set and for a NaN result, in
1526
* order to deal with the vagaries of different platforms. Also, a
1527
* zero result implies unreported underflow.
1531
if (errno != 0 || result == 0.0
1537
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1538
errmsg("result is out of range")));
1540
CheckFloat8Val(result);
1541
PG_RETURN_FLOAT8(result);
1546
* dlog1 - returns the natural logarithm of arg1
1549
dlog1(PG_FUNCTION_ARGS)
1551
float8 arg1 = PG_GETARG_FLOAT8(0);
1555
* Emit particular SQLSTATE error codes for ln(). This is required by
1560
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1561
errmsg("cannot take logarithm of zero")));
1564
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1565
errmsg("cannot take logarithm of a negative number")));
1569
CheckFloat8Val(result);
1570
PG_RETURN_FLOAT8(result);
1575
* dlog10 - returns the base 10 logarithm of arg1
1578
dlog10(PG_FUNCTION_ARGS)
1580
float8 arg1 = PG_GETARG_FLOAT8(0);
1584
* Emit particular SQLSTATE error codes for log(). The SQL spec
1585
* doesn't define log(), but it does define ln(), so it makes sense to
1586
* emit the same error code for an analogous error condition.
1590
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1591
errmsg("cannot take logarithm of zero")));
1594
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
1595
errmsg("cannot take logarithm of a negative number")));
1597
result = log10(arg1);
1599
CheckFloat8Val(result);
1600
PG_RETURN_FLOAT8(result);
1605
* dacos - returns the arccos of arg1 (radians)
1608
dacos(PG_FUNCTION_ARGS)
1610
float8 arg1 = PG_GETARG_FLOAT8(0);
1614
result = acos(arg1);
1621
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1622
errmsg("input is out of range")));
1624
CheckFloat8Val(result);
1625
PG_RETURN_FLOAT8(result);
1630
* dasin - returns the arcsin of arg1 (radians)
1633
dasin(PG_FUNCTION_ARGS)
1635
float8 arg1 = PG_GETARG_FLOAT8(0);
1639
result = asin(arg1);
1646
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1647
errmsg("input is out of range")));
1649
CheckFloat8Val(result);
1650
PG_RETURN_FLOAT8(result);
1655
* datan - returns the arctan of arg1 (radians)
1658
datan(PG_FUNCTION_ARGS)
1660
float8 arg1 = PG_GETARG_FLOAT8(0);
1664
result = atan(arg1);
1671
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1672
errmsg("input is out of range")));
1674
CheckFloat8Val(result);
1675
PG_RETURN_FLOAT8(result);
1680
* atan2 - returns the arctan2 of arg1 (radians)
1683
datan2(PG_FUNCTION_ARGS)
1685
float8 arg1 = PG_GETARG_FLOAT8(0);
1686
float8 arg2 = PG_GETARG_FLOAT8(1);
1690
result = atan2(arg1, arg2);
1697
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1698
errmsg("input is out of range")));
1700
CheckFloat8Val(result);
1701
PG_RETURN_FLOAT8(result);
1706
* dcos - returns the cosine of arg1 (radians)
1709
dcos(PG_FUNCTION_ARGS)
1711
float8 arg1 = PG_GETARG_FLOAT8(0);
1722
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1723
errmsg("input is out of range")));
1725
CheckFloat8Val(result);
1726
PG_RETURN_FLOAT8(result);
1731
* dcot - returns the cotangent of arg1 (radians)
1734
dcot(PG_FUNCTION_ARGS)
1736
float8 arg1 = PG_GETARG_FLOAT8(0);
1741
if (errno != 0 || result == 0.0
1747
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1748
errmsg("input is out of range")));
1750
result = 1.0 / result;
1751
CheckFloat8Val(result);
1752
PG_RETURN_FLOAT8(result);
1757
* dsin - returns the sine of arg1 (radians)
1760
dsin(PG_FUNCTION_ARGS)
1762
float8 arg1 = PG_GETARG_FLOAT8(0);
1773
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1774
errmsg("input is out of range")));
1776
CheckFloat8Val(result);
1777
PG_RETURN_FLOAT8(result);
1782
* dtan - returns the tangent of arg1 (radians)
1785
dtan(PG_FUNCTION_ARGS)
1787
float8 arg1 = PG_GETARG_FLOAT8(0);
1798
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1799
errmsg("input is out of range")));
1801
CheckFloat8Val(result);
1802
PG_RETURN_FLOAT8(result);
1807
* degrees - returns degrees converted from radians
1810
degrees(PG_FUNCTION_ARGS)
1812
float8 arg1 = PG_GETARG_FLOAT8(0);
1815
result = arg1 * (180.0 / M_PI);
1817
CheckFloat8Val(result);
1818
PG_RETURN_FLOAT8(result);
1823
* dpi - returns the constant PI
1826
dpi(PG_FUNCTION_ARGS)
1828
PG_RETURN_FLOAT8(M_PI);
1833
* radians - returns radians converted from degrees
1836
radians(PG_FUNCTION_ARGS)
1838
float8 arg1 = PG_GETARG_FLOAT8(0);
1841
result = arg1 * (M_PI / 180.0);
1843
CheckFloat8Val(result);
1844
PG_RETURN_FLOAT8(result);
1849
* drandom - returns a random number
1852
drandom(PG_FUNCTION_ARGS)
1856
/* result 0.0-1.0 */
1857
result = ((double) random()) / ((double) MAX_RANDOM_VALUE);
1859
PG_RETURN_FLOAT8(result);
1864
* setseed - set seed for the random number generator
1867
setseed(PG_FUNCTION_ARGS)
1869
float8 seed = PG_GETARG_FLOAT8(0);
1870
int iseed = (int) (seed * MAX_RANDOM_VALUE);
1872
srandom((unsigned int) iseed);
1874
PG_RETURN_INT32(iseed);
1880
* =========================
1881
* FLOAT AGGREGATE OPERATORS
1882
* =========================
1884
* float8_accum - accumulate for AVG(), STDDEV(), etc
1885
* float4_accum - same, but input data is float4
1886
* float8_avg - produce final result for float AVG()
1887
* float8_variance - produce final result for float VARIANCE()
1888
* float8_stddev - produce final result for float STDDEV()
1890
* The transition datatype for all these aggregates is a 3-element array
1891
* of float8, holding the values N, sum(X), sum(X*X) in that order.
1893
* Note that we represent N as a float to avoid having to build a special
1894
* datatype. Given a reasonable floating-point implementation, there should
1895
* be no accuracy loss unless N exceeds 2 ^ 52 or so (by which time the
1896
* user will have doubtless lost interest anyway...)
1900
check_float8_array(ArrayType *transarray, const char *caller)
1903
* We expect the input to be a 3-element float array; verify that. We
1904
* don't need to use deconstruct_array() since the array data is just
1905
* going to look like a C array of 3 float8 values.
1907
if (ARR_NDIM(transarray) != 1 ||
1908
ARR_DIMS(transarray)[0] != 3 ||
1909
ARR_ELEMTYPE(transarray) != FLOAT8OID)
1910
elog(ERROR, "%s: expected 3-element float8 array", caller);
1911
return (float8 *) ARR_DATA_PTR(transarray);
1915
float8_accum(PG_FUNCTION_ARGS)
1917
ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1918
float8 newval = PG_GETARG_FLOAT8(1);
1919
float8 *transvalues;
1923
Datum transdatums[3];
1926
transvalues = check_float8_array(transarray, "float8_accum");
1928
sumX = transvalues[1];
1929
sumX2 = transvalues[2];
1933
sumX2 += newval * newval;
1935
transdatums[0] = Float8GetDatumFast(N);
1936
transdatums[1] = Float8GetDatumFast(sumX);
1937
transdatums[2] = Float8GetDatumFast(sumX2);
1939
result = construct_array(transdatums, 3,
1941
sizeof(float8), false /* float8 byval */ , 'd');
1943
PG_RETURN_ARRAYTYPE_P(result);
1947
float4_accum(PG_FUNCTION_ARGS)
1949
ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1950
float4 newval4 = PG_GETARG_FLOAT4(1);
1951
float8 *transvalues;
1956
Datum transdatums[3];
1959
transvalues = check_float8_array(transarray, "float4_accum");
1961
sumX = transvalues[1];
1962
sumX2 = transvalues[2];
1964
/* Do arithmetic in float8 for best accuracy */
1969
sumX2 += newval * newval;
1971
transdatums[0] = Float8GetDatumFast(N);
1972
transdatums[1] = Float8GetDatumFast(sumX);
1973
transdatums[2] = Float8GetDatumFast(sumX2);
1975
result = construct_array(transdatums, 3,
1977
sizeof(float8), false /* float8 byval */ , 'd');
1979
PG_RETURN_ARRAYTYPE_P(result);
1983
float8_avg(PG_FUNCTION_ARGS)
1985
ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1986
float8 *transvalues;
1990
transvalues = check_float8_array(transarray, "float8_avg");
1992
sumX = transvalues[1];
1995
/* SQL92 defines AVG of no values to be NULL */
1999
PG_RETURN_FLOAT8(sumX / N);
2003
float8_variance(PG_FUNCTION_ARGS)
2005
ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2006
float8 *transvalues;
2012
transvalues = check_float8_array(transarray, "float8_variance");
2014
sumX = transvalues[1];
2015
sumX2 = transvalues[2];
2017
/* Sample variance is undefined when N is 0 or 1, so return NULL */
2021
numerator = N * sumX2 - sumX * sumX;
2023
/* Watch out for roundoff error producing a negative numerator */
2024
if (numerator <= 0.0)
2025
PG_RETURN_FLOAT8(0.0);
2027
PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
2031
float8_stddev(PG_FUNCTION_ARGS)
2033
ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2034
float8 *transvalues;
2040
transvalues = check_float8_array(transarray, "float8_stddev");
2042
sumX = transvalues[1];
2043
sumX2 = transvalues[2];
2045
/* Sample stddev is undefined when N is 0 or 1, so return NULL */
2049
numerator = N * sumX2 - sumX * sumX;
2051
/* Watch out for roundoff error producing a negative numerator */
2052
if (numerator <= 0.0)
2053
PG_RETURN_FLOAT8(0.0);
2055
PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));
2060
* ====================================
2061
* MIXED-PRECISION ARITHMETIC OPERATORS
2062
* ====================================
2066
* float48pl - returns arg1 + arg2
2067
* float48mi - returns arg1 - arg2
2068
* float48mul - returns arg1 * arg2
2069
* float48div - returns arg1 / arg2
2072
float48pl(PG_FUNCTION_ARGS)
2074
float4 arg1 = PG_GETARG_FLOAT4(0);
2075
float8 arg2 = PG_GETARG_FLOAT8(1);
2078
result = arg1 + arg2;
2079
CheckFloat8Val(result);
2080
PG_RETURN_FLOAT8(result);
2084
float48mi(PG_FUNCTION_ARGS)
2086
float4 arg1 = PG_GETARG_FLOAT4(0);
2087
float8 arg2 = PG_GETARG_FLOAT8(1);
2090
result = arg1 - arg2;
2091
CheckFloat8Val(result);
2092
PG_RETURN_FLOAT8(result);
2096
float48mul(PG_FUNCTION_ARGS)
2098
float4 arg1 = PG_GETARG_FLOAT4(0);
2099
float8 arg2 = PG_GETARG_FLOAT8(1);
2102
result = arg1 * arg2;
2103
CheckFloat8Val(result);
2104
PG_RETURN_FLOAT8(result);
2108
float48div(PG_FUNCTION_ARGS)
2110
float4 arg1 = PG_GETARG_FLOAT4(0);
2111
float8 arg2 = PG_GETARG_FLOAT8(1);
2116
(errcode(ERRCODE_DIVISION_BY_ZERO),
2117
errmsg("division by zero")));
2119
result = arg1 / arg2;
2120
CheckFloat8Val(result);
2121
PG_RETURN_FLOAT8(result);
2125
* float84pl - returns arg1 + arg2
2126
* float84mi - returns arg1 - arg2
2127
* float84mul - returns arg1 * arg2
2128
* float84div - returns arg1 / arg2
2131
float84pl(PG_FUNCTION_ARGS)
2133
float8 arg1 = PG_GETARG_FLOAT8(0);
2134
float4 arg2 = PG_GETARG_FLOAT4(1);
2137
result = arg1 + arg2;
2139
CheckFloat8Val(result);
2140
PG_RETURN_FLOAT8(result);
2144
float84mi(PG_FUNCTION_ARGS)
2146
float8 arg1 = PG_GETARG_FLOAT8(0);
2147
float4 arg2 = PG_GETARG_FLOAT4(1);
2150
result = arg1 - arg2;
2152
CheckFloat8Val(result);
2153
PG_RETURN_FLOAT8(result);
2157
float84mul(PG_FUNCTION_ARGS)
2159
float8 arg1 = PG_GETARG_FLOAT8(0);
2160
float4 arg2 = PG_GETARG_FLOAT4(1);
2163
result = arg1 * arg2;
2165
CheckFloat8Val(result);
2166
PG_RETURN_FLOAT8(result);
2170
float84div(PG_FUNCTION_ARGS)
2172
float8 arg1 = PG_GETARG_FLOAT8(0);
2173
float4 arg2 = PG_GETARG_FLOAT4(1);
2178
(errcode(ERRCODE_DIVISION_BY_ZERO),
2179
errmsg("division by zero")));
2181
result = arg1 / arg2;
2183
CheckFloat8Val(result);
2184
PG_RETURN_FLOAT8(result);
2188
* ====================
2189
* COMPARISON OPERATORS
2190
* ====================
2194
* float48{eq,ne,lt,le,gt,ge} - float4/float8 comparison operations
2197
float48eq(PG_FUNCTION_ARGS)
2199
float4 arg1 = PG_GETARG_FLOAT4(0);
2200
float8 arg2 = PG_GETARG_FLOAT8(1);
2202
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
2206
float48ne(PG_FUNCTION_ARGS)
2208
float4 arg1 = PG_GETARG_FLOAT4(0);
2209
float8 arg2 = PG_GETARG_FLOAT8(1);
2211
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
2215
float48lt(PG_FUNCTION_ARGS)
2217
float4 arg1 = PG_GETARG_FLOAT4(0);
2218
float8 arg2 = PG_GETARG_FLOAT8(1);
2220
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
2224
float48le(PG_FUNCTION_ARGS)
2226
float4 arg1 = PG_GETARG_FLOAT4(0);
2227
float8 arg2 = PG_GETARG_FLOAT8(1);
2229
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
2233
float48gt(PG_FUNCTION_ARGS)
2235
float4 arg1 = PG_GETARG_FLOAT4(0);
2236
float8 arg2 = PG_GETARG_FLOAT8(1);
2238
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
2242
float48ge(PG_FUNCTION_ARGS)
2244
float4 arg1 = PG_GETARG_FLOAT4(0);
2245
float8 arg2 = PG_GETARG_FLOAT8(1);
2247
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
2251
* float84{eq,ne,lt,le,gt,ge} - float8/float4 comparison operations
2254
float84eq(PG_FUNCTION_ARGS)
2256
float8 arg1 = PG_GETARG_FLOAT8(0);
2257
float4 arg2 = PG_GETARG_FLOAT4(1);
2259
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
2263
float84ne(PG_FUNCTION_ARGS)
2265
float8 arg1 = PG_GETARG_FLOAT8(0);
2266
float4 arg2 = PG_GETARG_FLOAT4(1);
2268
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
2272
float84lt(PG_FUNCTION_ARGS)
2274
float8 arg1 = PG_GETARG_FLOAT8(0);
2275
float4 arg2 = PG_GETARG_FLOAT4(1);
2277
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
2281
float84le(PG_FUNCTION_ARGS)
2283
float8 arg1 = PG_GETARG_FLOAT8(0);
2284
float4 arg2 = PG_GETARG_FLOAT4(1);
2286
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
2290
float84gt(PG_FUNCTION_ARGS)
2292
float8 arg1 = PG_GETARG_FLOAT8(0);
2293
float4 arg2 = PG_GETARG_FLOAT4(1);
2295
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
2299
float84ge(PG_FUNCTION_ARGS)
2301
float8 arg1 = PG_GETARG_FLOAT8(0);
2302
float4 arg2 = PG_GETARG_FLOAT4(1);
2304
PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
2307
/* ========== PRIVATE ROUTINES ========== */
2313
int isneg = (x < 0.0);
2314
double tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
2316
return isneg ? -tmpres : tmpres;
2319
#endif /* !HAVE_CBRT */