00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <ctype.h>
00018 #include <float.h>
00019 #include <math.h>
00020 #include <limits.h>
00021
00022 #include "catalog/pg_type.h"
00023 #include "libpq/pqformat.h"
00024 #include "utils/array.h"
00025 #include "utils/builtins.h"
00026 #include "utils/sortsupport.h"
00027
00028
00029 #ifndef M_PI
00030
00031 #define M_PI 3.14159265358979323846
00032 #endif
00033
00034
00035
00036
00037 #if defined(WIN32) && !defined(NAN)
00038 static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
00039
00040 #define NAN (*(const double *) nan)
00041 #endif
00042
00043
00044 #define MAXFLOATWIDTH 64
00045 #define MAXDOUBLEWIDTH 128
00046
00047
00048
00049
00050 #define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid) \
00051 do { \
00052 if (isinf(val) && !(inf_is_valid)) \
00053 ereport(ERROR, \
00054 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
00055 errmsg("value out of range: overflow"))); \
00056 \
00057 if ((val) == 0.0 && !(zero_is_valid)) \
00058 ereport(ERROR, \
00059 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
00060 errmsg("value out of range: underflow"))); \
00061 } while(0)
00062
00063
00064
00065
00066
00067
00068 int extra_float_digits = 0;
00069
00070
00071 static int float4_cmp_internal(float4 a, float4 b);
00072 static int float8_cmp_internal(float8 a, float8 b);
00073
00074 #ifndef HAVE_CBRT
00075
00076
00077
00078
00079
00080
00081
00082
00083 #define cbrt my_cbrt
00084 static double cbrt(double x);
00085 #endif
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 double
00098 get_float8_infinity(void)
00099 {
00100 #ifdef INFINITY
00101
00102 return (double) INFINITY;
00103 #else
00104
00105
00106
00107
00108
00109
00110 return (double) (HUGE_VAL * HUGE_VAL);
00111 #endif
00112 }
00113
00114 float
00115 get_float4_infinity(void)
00116 {
00117 #ifdef INFINITY
00118
00119 return (float) INFINITY;
00120 #else
00121
00122
00123
00124
00125
00126
00127 return (float) (HUGE_VAL * HUGE_VAL);
00128 #endif
00129 }
00130
00131 double
00132 get_float8_nan(void)
00133 {
00134
00135 #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
00136
00137 return (double) NAN;
00138 #else
00139
00140 return (double) (0.0 / 0.0);
00141 #endif
00142 }
00143
00144 float
00145 get_float4_nan(void)
00146 {
00147 #ifdef NAN
00148
00149 return (float) NAN;
00150 #else
00151
00152 return (float) (0.0 / 0.0);
00153 #endif
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 int
00165 is_infinite(double val)
00166 {
00167 int inf = isinf(val);
00168
00169 if (inf == 0)
00170 return 0;
00171 else if (val > 0)
00172 return 1;
00173 else
00174 return -1;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 Datum
00186 float4in(PG_FUNCTION_ARGS)
00187 {
00188 char *num = PG_GETARG_CSTRING(0);
00189 char *orig_num;
00190 double val;
00191 char *endptr;
00192
00193
00194
00195
00196
00197
00198 orig_num = num;
00199
00200
00201
00202
00203
00204 if (*num == '\0')
00205 ereport(ERROR,
00206 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00207 errmsg("invalid input syntax for type real: \"%s\"",
00208 orig_num)));
00209
00210
00211 while (*num != '\0' && isspace((unsigned char) *num))
00212 num++;
00213
00214 errno = 0;
00215 val = strtod(num, &endptr);
00216
00217
00218 if (endptr == num || errno != 0)
00219 {
00220 int save_errno = errno;
00221
00222
00223
00224
00225
00226
00227 if (pg_strncasecmp(num, "NaN", 3) == 0)
00228 {
00229 val = get_float4_nan();
00230 endptr = num + 3;
00231 }
00232 else if (pg_strncasecmp(num, "Infinity", 8) == 0)
00233 {
00234 val = get_float4_infinity();
00235 endptr = num + 8;
00236 }
00237 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
00238 {
00239 val = -get_float4_infinity();
00240 endptr = num + 9;
00241 }
00242 else if (save_errno == ERANGE)
00243 {
00244
00245
00246
00247
00248
00249
00250
00251 if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
00252 ereport(ERROR,
00253 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00254 errmsg("\"%s\" is out of range for type real",
00255 orig_num)));
00256 }
00257 else
00258 ereport(ERROR,
00259 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00260 errmsg("invalid input syntax for type real: \"%s\"",
00261 orig_num)));
00262 }
00263 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
00264 else
00265 {
00266
00267
00268
00269
00270
00271 if (endptr != num && endptr[-1] == '\0')
00272 endptr--;
00273 }
00274 #endif
00275
00276 #ifdef HAVE_BUGGY_IRIX_STRTOD
00277
00278
00279
00280
00281
00282
00283 if (isinf(val))
00284 {
00285 if (pg_strncasecmp(num, "Infinity", 8) == 0)
00286 {
00287 val = get_float4_infinity();
00288 endptr = num + 8;
00289 }
00290 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
00291 {
00292 val = -get_float4_infinity();
00293 endptr = num + 9;
00294 }
00295 else if (pg_strncasecmp(num, "-inf", 4) == 0)
00296 {
00297 val = -get_float4_infinity();
00298 endptr = num + 4;
00299 }
00300 }
00301 #endif
00302
00303
00304 while (*endptr != '\0' && isspace((unsigned char) *endptr))
00305 endptr++;
00306
00307
00308 if (*endptr != '\0')
00309 ereport(ERROR,
00310 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00311 errmsg("invalid input syntax for type real: \"%s\"",
00312 orig_num)));
00313
00314
00315
00316
00317
00318 CHECKFLOATVAL((float4) val, isinf(val), val == 0);
00319
00320 PG_RETURN_FLOAT4((float4) val);
00321 }
00322
00323
00324
00325
00326
00327 Datum
00328 float4out(PG_FUNCTION_ARGS)
00329 {
00330 float4 num = PG_GETARG_FLOAT4(0);
00331 char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
00332
00333 if (isnan(num))
00334 PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
00335
00336 switch (is_infinite(num))
00337 {
00338 case 1:
00339 strcpy(ascii, "Infinity");
00340 break;
00341 case -1:
00342 strcpy(ascii, "-Infinity");
00343 break;
00344 default:
00345 {
00346 int ndig = FLT_DIG + extra_float_digits;
00347
00348 if (ndig < 1)
00349 ndig = 1;
00350
00351 snprintf(ascii, MAXFLOATWIDTH + 1, "%.*g", ndig, num);
00352 }
00353 }
00354
00355 PG_RETURN_CSTRING(ascii);
00356 }
00357
00358
00359
00360
00361 Datum
00362 float4recv(PG_FUNCTION_ARGS)
00363 {
00364 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
00365
00366 PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));
00367 }
00368
00369
00370
00371
00372 Datum
00373 float4send(PG_FUNCTION_ARGS)
00374 {
00375 float4 num = PG_GETARG_FLOAT4(0);
00376 StringInfoData buf;
00377
00378 pq_begintypsend(&buf);
00379 pq_sendfloat4(&buf, num);
00380 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390 Datum
00391 float8in(PG_FUNCTION_ARGS)
00392 {
00393 char *num = PG_GETARG_CSTRING(0);
00394 char *orig_num;
00395 double val;
00396 char *endptr;
00397
00398
00399
00400
00401
00402
00403 orig_num = num;
00404
00405
00406
00407
00408
00409 if (*num == '\0')
00410 ereport(ERROR,
00411 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00412 errmsg("invalid input syntax for type double precision: \"%s\"",
00413 orig_num)));
00414
00415
00416 while (*num != '\0' && isspace((unsigned char) *num))
00417 num++;
00418
00419 errno = 0;
00420 val = strtod(num, &endptr);
00421
00422
00423 if (endptr == num || errno != 0)
00424 {
00425 int save_errno = errno;
00426
00427
00428
00429
00430
00431
00432 if (pg_strncasecmp(num, "NaN", 3) == 0)
00433 {
00434 val = get_float8_nan();
00435 endptr = num + 3;
00436 }
00437 else if (pg_strncasecmp(num, "Infinity", 8) == 0)
00438 {
00439 val = get_float8_infinity();
00440 endptr = num + 8;
00441 }
00442 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
00443 {
00444 val = -get_float8_infinity();
00445 endptr = num + 9;
00446 }
00447 else if (save_errno == ERANGE)
00448 {
00449
00450
00451
00452
00453
00454
00455
00456 if (val == 0.0 || val >= HUGE_VAL || val <= -HUGE_VAL)
00457 ereport(ERROR,
00458 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00459 errmsg("\"%s\" is out of range for type double precision",
00460 orig_num)));
00461 }
00462 else
00463 ereport(ERROR,
00464 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00465 errmsg("invalid input syntax for type double precision: \"%s\"",
00466 orig_num)));
00467 }
00468 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
00469 else
00470 {
00471
00472
00473
00474
00475
00476 if (endptr != num && endptr[-1] == '\0')
00477 endptr--;
00478 }
00479 #endif
00480
00481 #ifdef HAVE_BUGGY_IRIX_STRTOD
00482
00483
00484
00485
00486
00487
00488 if (isinf(val))
00489 {
00490 if (pg_strncasecmp(num, "Infinity", 8) == 0)
00491 {
00492 val = get_float8_infinity();
00493 endptr = num + 8;
00494 }
00495 else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
00496 {
00497 val = -get_float8_infinity();
00498 endptr = num + 9;
00499 }
00500 else if (pg_strncasecmp(num, "-inf", 4) == 0)
00501 {
00502 val = -get_float8_infinity();
00503 endptr = num + 4;
00504 }
00505 }
00506 #endif
00507
00508
00509 while (*endptr != '\0' && isspace((unsigned char) *endptr))
00510 endptr++;
00511
00512
00513 if (*endptr != '\0')
00514 ereport(ERROR,
00515 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00516 errmsg("invalid input syntax for type double precision: \"%s\"",
00517 orig_num)));
00518
00519 CHECKFLOATVAL(val, true, true);
00520
00521 PG_RETURN_FLOAT8(val);
00522 }
00523
00524
00525
00526
00527
00528 Datum
00529 float8out(PG_FUNCTION_ARGS)
00530 {
00531 float8 num = PG_GETARG_FLOAT8(0);
00532 char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
00533
00534 if (isnan(num))
00535 PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
00536
00537 switch (is_infinite(num))
00538 {
00539 case 1:
00540 strcpy(ascii, "Infinity");
00541 break;
00542 case -1:
00543 strcpy(ascii, "-Infinity");
00544 break;
00545 default:
00546 {
00547 int ndig = DBL_DIG + extra_float_digits;
00548
00549 if (ndig < 1)
00550 ndig = 1;
00551
00552 snprintf(ascii, MAXDOUBLEWIDTH + 1, "%.*g", ndig, num);
00553 }
00554 }
00555
00556 PG_RETURN_CSTRING(ascii);
00557 }
00558
00559
00560
00561
00562 Datum
00563 float8recv(PG_FUNCTION_ARGS)
00564 {
00565 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
00566
00567 PG_RETURN_FLOAT8(pq_getmsgfloat8(buf));
00568 }
00569
00570
00571
00572
00573 Datum
00574 float8send(PG_FUNCTION_ARGS)
00575 {
00576 float8 num = PG_GETARG_FLOAT8(0);
00577 StringInfoData buf;
00578
00579 pq_begintypsend(&buf);
00580 pq_sendfloat8(&buf, num);
00581 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 Datum
00598 float4abs(PG_FUNCTION_ARGS)
00599 {
00600 float4 arg1 = PG_GETARG_FLOAT4(0);
00601
00602 PG_RETURN_FLOAT4((float4) fabs(arg1));
00603 }
00604
00605
00606
00607
00608 Datum
00609 float4um(PG_FUNCTION_ARGS)
00610 {
00611 float4 arg1 = PG_GETARG_FLOAT4(0);
00612 float4 result;
00613
00614 result = -arg1;
00615 PG_RETURN_FLOAT4(result);
00616 }
00617
00618 Datum
00619 float4up(PG_FUNCTION_ARGS)
00620 {
00621 float4 arg = PG_GETARG_FLOAT4(0);
00622
00623 PG_RETURN_FLOAT4(arg);
00624 }
00625
00626 Datum
00627 float4larger(PG_FUNCTION_ARGS)
00628 {
00629 float4 arg1 = PG_GETARG_FLOAT4(0);
00630 float4 arg2 = PG_GETARG_FLOAT4(1);
00631 float4 result;
00632
00633 if (float4_cmp_internal(arg1, arg2) > 0)
00634 result = arg1;
00635 else
00636 result = arg2;
00637 PG_RETURN_FLOAT4(result);
00638 }
00639
00640 Datum
00641 float4smaller(PG_FUNCTION_ARGS)
00642 {
00643 float4 arg1 = PG_GETARG_FLOAT4(0);
00644 float4 arg2 = PG_GETARG_FLOAT4(1);
00645 float4 result;
00646
00647 if (float4_cmp_internal(arg1, arg2) < 0)
00648 result = arg1;
00649 else
00650 result = arg2;
00651 PG_RETURN_FLOAT4(result);
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 Datum
00664 float8abs(PG_FUNCTION_ARGS)
00665 {
00666 float8 arg1 = PG_GETARG_FLOAT8(0);
00667
00668 PG_RETURN_FLOAT8(fabs(arg1));
00669 }
00670
00671
00672
00673
00674
00675 Datum
00676 float8um(PG_FUNCTION_ARGS)
00677 {
00678 float8 arg1 = PG_GETARG_FLOAT8(0);
00679 float8 result;
00680
00681 result = -arg1;
00682 PG_RETURN_FLOAT8(result);
00683 }
00684
00685 Datum
00686 float8up(PG_FUNCTION_ARGS)
00687 {
00688 float8 arg = PG_GETARG_FLOAT8(0);
00689
00690 PG_RETURN_FLOAT8(arg);
00691 }
00692
00693 Datum
00694 float8larger(PG_FUNCTION_ARGS)
00695 {
00696 float8 arg1 = PG_GETARG_FLOAT8(0);
00697 float8 arg2 = PG_GETARG_FLOAT8(1);
00698 float8 result;
00699
00700 if (float8_cmp_internal(arg1, arg2) > 0)
00701 result = arg1;
00702 else
00703 result = arg2;
00704 PG_RETURN_FLOAT8(result);
00705 }
00706
00707 Datum
00708 float8smaller(PG_FUNCTION_ARGS)
00709 {
00710 float8 arg1 = PG_GETARG_FLOAT8(0);
00711 float8 arg2 = PG_GETARG_FLOAT8(1);
00712 float8 result;
00713
00714 if (float8_cmp_internal(arg1, arg2) < 0)
00715 result = arg1;
00716 else
00717 result = arg2;
00718 PG_RETURN_FLOAT8(result);
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734 Datum
00735 float4pl(PG_FUNCTION_ARGS)
00736 {
00737 float4 arg1 = PG_GETARG_FLOAT4(0);
00738 float4 arg2 = PG_GETARG_FLOAT4(1);
00739 float4 result;
00740
00741 result = arg1 + arg2;
00742
00743
00744
00745
00746
00747
00748
00749
00750 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
00751 PG_RETURN_FLOAT4(result);
00752 }
00753
00754 Datum
00755 float4mi(PG_FUNCTION_ARGS)
00756 {
00757 float4 arg1 = PG_GETARG_FLOAT4(0);
00758 float4 arg2 = PG_GETARG_FLOAT4(1);
00759 float4 result;
00760
00761 result = arg1 - arg2;
00762 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
00763 PG_RETURN_FLOAT4(result);
00764 }
00765
00766 Datum
00767 float4mul(PG_FUNCTION_ARGS)
00768 {
00769 float4 arg1 = PG_GETARG_FLOAT4(0);
00770 float4 arg2 = PG_GETARG_FLOAT4(1);
00771 float4 result;
00772
00773 result = arg1 * arg2;
00774 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
00775 arg1 == 0 || arg2 == 0);
00776 PG_RETURN_FLOAT4(result);
00777 }
00778
00779 Datum
00780 float4div(PG_FUNCTION_ARGS)
00781 {
00782 float4 arg1 = PG_GETARG_FLOAT4(0);
00783 float4 arg2 = PG_GETARG_FLOAT4(1);
00784 float4 result;
00785
00786 if (arg2 == 0.0)
00787 ereport(ERROR,
00788 (errcode(ERRCODE_DIVISION_BY_ZERO),
00789 errmsg("division by zero")));
00790
00791 result = arg1 / arg2;
00792
00793 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
00794 PG_RETURN_FLOAT4(result);
00795 }
00796
00797
00798
00799
00800
00801
00802
00803 Datum
00804 float8pl(PG_FUNCTION_ARGS)
00805 {
00806 float8 arg1 = PG_GETARG_FLOAT8(0);
00807 float8 arg2 = PG_GETARG_FLOAT8(1);
00808 float8 result;
00809
00810 result = arg1 + arg2;
00811
00812 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
00813 PG_RETURN_FLOAT8(result);
00814 }
00815
00816 Datum
00817 float8mi(PG_FUNCTION_ARGS)
00818 {
00819 float8 arg1 = PG_GETARG_FLOAT8(0);
00820 float8 arg2 = PG_GETARG_FLOAT8(1);
00821 float8 result;
00822
00823 result = arg1 - arg2;
00824
00825 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
00826 PG_RETURN_FLOAT8(result);
00827 }
00828
00829 Datum
00830 float8mul(PG_FUNCTION_ARGS)
00831 {
00832 float8 arg1 = PG_GETARG_FLOAT8(0);
00833 float8 arg2 = PG_GETARG_FLOAT8(1);
00834 float8 result;
00835
00836 result = arg1 * arg2;
00837
00838 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
00839 arg1 == 0 || arg2 == 0);
00840 PG_RETURN_FLOAT8(result);
00841 }
00842
00843 Datum
00844 float8div(PG_FUNCTION_ARGS)
00845 {
00846 float8 arg1 = PG_GETARG_FLOAT8(0);
00847 float8 arg2 = PG_GETARG_FLOAT8(1);
00848 float8 result;
00849
00850 if (arg2 == 0.0)
00851 ereport(ERROR,
00852 (errcode(ERRCODE_DIVISION_BY_ZERO),
00853 errmsg("division by zero")));
00854
00855 result = arg1 / arg2;
00856
00857 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
00858 PG_RETURN_FLOAT8(result);
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 static int
00872 float4_cmp_internal(float4 a, float4 b)
00873 {
00874
00875
00876
00877
00878
00879 if (isnan(a))
00880 {
00881 if (isnan(b))
00882 return 0;
00883 else
00884 return 1;
00885 }
00886 else if (isnan(b))
00887 {
00888 return -1;
00889 }
00890 else
00891 {
00892 if (a > b)
00893 return 1;
00894 else if (a < b)
00895 return -1;
00896 else
00897 return 0;
00898 }
00899 }
00900
00901 Datum
00902 float4eq(PG_FUNCTION_ARGS)
00903 {
00904 float4 arg1 = PG_GETARG_FLOAT4(0);
00905 float4 arg2 = PG_GETARG_FLOAT4(1);
00906
00907 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);
00908 }
00909
00910 Datum
00911 float4ne(PG_FUNCTION_ARGS)
00912 {
00913 float4 arg1 = PG_GETARG_FLOAT4(0);
00914 float4 arg2 = PG_GETARG_FLOAT4(1);
00915
00916 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);
00917 }
00918
00919 Datum
00920 float4lt(PG_FUNCTION_ARGS)
00921 {
00922 float4 arg1 = PG_GETARG_FLOAT4(0);
00923 float4 arg2 = PG_GETARG_FLOAT4(1);
00924
00925 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);
00926 }
00927
00928 Datum
00929 float4le(PG_FUNCTION_ARGS)
00930 {
00931 float4 arg1 = PG_GETARG_FLOAT4(0);
00932 float4 arg2 = PG_GETARG_FLOAT4(1);
00933
00934 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);
00935 }
00936
00937 Datum
00938 float4gt(PG_FUNCTION_ARGS)
00939 {
00940 float4 arg1 = PG_GETARG_FLOAT4(0);
00941 float4 arg2 = PG_GETARG_FLOAT4(1);
00942
00943 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);
00944 }
00945
00946 Datum
00947 float4ge(PG_FUNCTION_ARGS)
00948 {
00949 float4 arg1 = PG_GETARG_FLOAT4(0);
00950 float4 arg2 = PG_GETARG_FLOAT4(1);
00951
00952 PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);
00953 }
00954
00955 Datum
00956 btfloat4cmp(PG_FUNCTION_ARGS)
00957 {
00958 float4 arg1 = PG_GETARG_FLOAT4(0);
00959 float4 arg2 = PG_GETARG_FLOAT4(1);
00960
00961 PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
00962 }
00963
00964 static int
00965 btfloat4fastcmp(Datum x, Datum y, SortSupport ssup)
00966 {
00967 float4 arg1 = DatumGetFloat4(x);
00968 float4 arg2 = DatumGetFloat4(y);
00969
00970 return float4_cmp_internal(arg1, arg2);
00971 }
00972
00973 Datum
00974 btfloat4sortsupport(PG_FUNCTION_ARGS)
00975 {
00976 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00977
00978 ssup->comparator = btfloat4fastcmp;
00979 PG_RETURN_VOID();
00980 }
00981
00982
00983
00984
00985 static int
00986 float8_cmp_internal(float8 a, float8 b)
00987 {
00988
00989
00990
00991
00992
00993 if (isnan(a))
00994 {
00995 if (isnan(b))
00996 return 0;
00997 else
00998 return 1;
00999 }
01000 else if (isnan(b))
01001 {
01002 return -1;
01003 }
01004 else
01005 {
01006 if (a > b)
01007 return 1;
01008 else if (a < b)
01009 return -1;
01010 else
01011 return 0;
01012 }
01013 }
01014
01015 Datum
01016 float8eq(PG_FUNCTION_ARGS)
01017 {
01018 float8 arg1 = PG_GETARG_FLOAT8(0);
01019 float8 arg2 = PG_GETARG_FLOAT8(1);
01020
01021 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
01022 }
01023
01024 Datum
01025 float8ne(PG_FUNCTION_ARGS)
01026 {
01027 float8 arg1 = PG_GETARG_FLOAT8(0);
01028 float8 arg2 = PG_GETARG_FLOAT8(1);
01029
01030 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
01031 }
01032
01033 Datum
01034 float8lt(PG_FUNCTION_ARGS)
01035 {
01036 float8 arg1 = PG_GETARG_FLOAT8(0);
01037 float8 arg2 = PG_GETARG_FLOAT8(1);
01038
01039 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
01040 }
01041
01042 Datum
01043 float8le(PG_FUNCTION_ARGS)
01044 {
01045 float8 arg1 = PG_GETARG_FLOAT8(0);
01046 float8 arg2 = PG_GETARG_FLOAT8(1);
01047
01048 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
01049 }
01050
01051 Datum
01052 float8gt(PG_FUNCTION_ARGS)
01053 {
01054 float8 arg1 = PG_GETARG_FLOAT8(0);
01055 float8 arg2 = PG_GETARG_FLOAT8(1);
01056
01057 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
01058 }
01059
01060 Datum
01061 float8ge(PG_FUNCTION_ARGS)
01062 {
01063 float8 arg1 = PG_GETARG_FLOAT8(0);
01064 float8 arg2 = PG_GETARG_FLOAT8(1);
01065
01066 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
01067 }
01068
01069 Datum
01070 btfloat8cmp(PG_FUNCTION_ARGS)
01071 {
01072 float8 arg1 = PG_GETARG_FLOAT8(0);
01073 float8 arg2 = PG_GETARG_FLOAT8(1);
01074
01075 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
01076 }
01077
01078 static int
01079 btfloat8fastcmp(Datum x, Datum y, SortSupport ssup)
01080 {
01081 float8 arg1 = DatumGetFloat8(x);
01082 float8 arg2 = DatumGetFloat8(y);
01083
01084 return float8_cmp_internal(arg1, arg2);
01085 }
01086
01087 Datum
01088 btfloat8sortsupport(PG_FUNCTION_ARGS)
01089 {
01090 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
01091
01092 ssup->comparator = btfloat8fastcmp;
01093 PG_RETURN_VOID();
01094 }
01095
01096 Datum
01097 btfloat48cmp(PG_FUNCTION_ARGS)
01098 {
01099 float4 arg1 = PG_GETARG_FLOAT4(0);
01100 float8 arg2 = PG_GETARG_FLOAT8(1);
01101
01102
01103 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
01104 }
01105
01106 Datum
01107 btfloat84cmp(PG_FUNCTION_ARGS)
01108 {
01109 float8 arg1 = PG_GETARG_FLOAT8(0);
01110 float4 arg2 = PG_GETARG_FLOAT4(1);
01111
01112
01113 PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126 Datum
01127 ftod(PG_FUNCTION_ARGS)
01128 {
01129 float4 num = PG_GETARG_FLOAT4(0);
01130
01131 PG_RETURN_FLOAT8((float8) num);
01132 }
01133
01134
01135
01136
01137
01138 Datum
01139 dtof(PG_FUNCTION_ARGS)
01140 {
01141 float8 num = PG_GETARG_FLOAT8(0);
01142
01143 CHECKFLOATVAL((float4) num, isinf(num), num == 0);
01144
01145 PG_RETURN_FLOAT4((float4) num);
01146 }
01147
01148
01149
01150
01151
01152 Datum
01153 dtoi4(PG_FUNCTION_ARGS)
01154 {
01155 float8 num = PG_GETARG_FLOAT8(0);
01156 int32 result;
01157
01158
01159 if (num < INT_MIN || num > INT_MAX || isnan(num))
01160 ereport(ERROR,
01161 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01162 errmsg("integer out of range")));
01163
01164 result = (int32) rint(num);
01165 PG_RETURN_INT32(result);
01166 }
01167
01168
01169
01170
01171
01172 Datum
01173 dtoi2(PG_FUNCTION_ARGS)
01174 {
01175 float8 num = PG_GETARG_FLOAT8(0);
01176
01177 if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
01178 ereport(ERROR,
01179 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01180 errmsg("smallint out of range")));
01181
01182 PG_RETURN_INT16((int16) rint(num));
01183 }
01184
01185
01186
01187
01188
01189 Datum
01190 i4tod(PG_FUNCTION_ARGS)
01191 {
01192 int32 num = PG_GETARG_INT32(0);
01193
01194 PG_RETURN_FLOAT8((float8) num);
01195 }
01196
01197
01198
01199
01200
01201 Datum
01202 i2tod(PG_FUNCTION_ARGS)
01203 {
01204 int16 num = PG_GETARG_INT16(0);
01205
01206 PG_RETURN_FLOAT8((float8) num);
01207 }
01208
01209
01210
01211
01212
01213 Datum
01214 ftoi4(PG_FUNCTION_ARGS)
01215 {
01216 float4 num = PG_GETARG_FLOAT4(0);
01217
01218 if (num < INT_MIN || num > INT_MAX || isnan(num))
01219 ereport(ERROR,
01220 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01221 errmsg("integer out of range")));
01222
01223 PG_RETURN_INT32((int32) rint(num));
01224 }
01225
01226
01227
01228
01229
01230 Datum
01231 ftoi2(PG_FUNCTION_ARGS)
01232 {
01233 float4 num = PG_GETARG_FLOAT4(0);
01234
01235 if (num < SHRT_MIN || num > SHRT_MAX || isnan(num))
01236 ereport(ERROR,
01237 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01238 errmsg("smallint out of range")));
01239
01240 PG_RETURN_INT16((int16) rint(num));
01241 }
01242
01243
01244
01245
01246
01247 Datum
01248 i4tof(PG_FUNCTION_ARGS)
01249 {
01250 int32 num = PG_GETARG_INT32(0);
01251
01252 PG_RETURN_FLOAT4((float4) num);
01253 }
01254
01255
01256
01257
01258
01259 Datum
01260 i2tof(PG_FUNCTION_ARGS)
01261 {
01262 int16 num = PG_GETARG_INT16(0);
01263
01264 PG_RETURN_FLOAT4((float4) num);
01265 }
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 Datum
01278 dround(PG_FUNCTION_ARGS)
01279 {
01280 float8 arg1 = PG_GETARG_FLOAT8(0);
01281
01282 PG_RETURN_FLOAT8(rint(arg1));
01283 }
01284
01285
01286
01287
01288
01289 Datum
01290 dceil(PG_FUNCTION_ARGS)
01291 {
01292 float8 arg1 = PG_GETARG_FLOAT8(0);
01293
01294 PG_RETURN_FLOAT8(ceil(arg1));
01295 }
01296
01297
01298
01299
01300
01301 Datum
01302 dfloor(PG_FUNCTION_ARGS)
01303 {
01304 float8 arg1 = PG_GETARG_FLOAT8(0);
01305
01306 PG_RETURN_FLOAT8(floor(arg1));
01307 }
01308
01309
01310
01311
01312
01313
01314 Datum
01315 dsign(PG_FUNCTION_ARGS)
01316 {
01317 float8 arg1 = PG_GETARG_FLOAT8(0);
01318 float8 result;
01319
01320 if (arg1 > 0)
01321 result = 1.0;
01322 else if (arg1 < 0)
01323 result = -1.0;
01324 else
01325 result = 0.0;
01326
01327 PG_RETURN_FLOAT8(result);
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337 Datum
01338 dtrunc(PG_FUNCTION_ARGS)
01339 {
01340 float8 arg1 = PG_GETARG_FLOAT8(0);
01341 float8 result;
01342
01343 if (arg1 >= 0)
01344 result = floor(arg1);
01345 else
01346 result = -floor(-arg1);
01347
01348 PG_RETURN_FLOAT8(result);
01349 }
01350
01351
01352
01353
01354
01355 Datum
01356 dsqrt(PG_FUNCTION_ARGS)
01357 {
01358 float8 arg1 = PG_GETARG_FLOAT8(0);
01359 float8 result;
01360
01361 if (arg1 < 0)
01362 ereport(ERROR,
01363 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
01364 errmsg("cannot take square root of a negative number")));
01365
01366 result = sqrt(arg1);
01367
01368 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
01369 PG_RETURN_FLOAT8(result);
01370 }
01371
01372
01373
01374
01375
01376 Datum
01377 dcbrt(PG_FUNCTION_ARGS)
01378 {
01379 float8 arg1 = PG_GETARG_FLOAT8(0);
01380 float8 result;
01381
01382 result = cbrt(arg1);
01383 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
01384 PG_RETURN_FLOAT8(result);
01385 }
01386
01387
01388
01389
01390
01391 Datum
01392 dpow(PG_FUNCTION_ARGS)
01393 {
01394 float8 arg1 = PG_GETARG_FLOAT8(0);
01395 float8 arg2 = PG_GETARG_FLOAT8(1);
01396 float8 result;
01397
01398
01399
01400
01401
01402
01403 if (arg1 == 0 && arg2 < 0)
01404 ereport(ERROR,
01405 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
01406 errmsg("zero raised to a negative power is undefined")));
01407 if (arg1 < 0 && floor(arg2) != arg2)
01408 ereport(ERROR,
01409 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
01410 errmsg("a negative number raised to a non-integer power yields a complex result")));
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421 errno = 0;
01422 result = pow(arg1, arg2);
01423 if (errno == EDOM && isnan(result))
01424 {
01425 if ((fabs(arg1) > 1 && arg2 >= 0) || (fabs(arg1) < 1 && arg2 < 0))
01426
01427 result = get_float8_infinity();
01428 else if (fabs(arg1) != 1)
01429 result = 0;
01430 else
01431 result = 1;
01432 }
01433 else if (errno == ERANGE && result != 0 && !isinf(result))
01434 result = get_float8_infinity();
01435
01436 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
01437 PG_RETURN_FLOAT8(result);
01438 }
01439
01440
01441
01442
01443
01444 Datum
01445 dexp(PG_FUNCTION_ARGS)
01446 {
01447 float8 arg1 = PG_GETARG_FLOAT8(0);
01448 float8 result;
01449
01450 errno = 0;
01451 result = exp(arg1);
01452 if (errno == ERANGE && result != 0 && !isinf(result))
01453 result = get_float8_infinity();
01454
01455 CHECKFLOATVAL(result, isinf(arg1), false);
01456 PG_RETURN_FLOAT8(result);
01457 }
01458
01459
01460
01461
01462
01463 Datum
01464 dlog1(PG_FUNCTION_ARGS)
01465 {
01466 float8 arg1 = PG_GETARG_FLOAT8(0);
01467 float8 result;
01468
01469
01470
01471
01472
01473 if (arg1 == 0.0)
01474 ereport(ERROR,
01475 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
01476 errmsg("cannot take logarithm of zero")));
01477 if (arg1 < 0)
01478 ereport(ERROR,
01479 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
01480 errmsg("cannot take logarithm of a negative number")));
01481
01482 result = log(arg1);
01483
01484 CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
01485 PG_RETURN_FLOAT8(result);
01486 }
01487
01488
01489
01490
01491
01492 Datum
01493 dlog10(PG_FUNCTION_ARGS)
01494 {
01495 float8 arg1 = PG_GETARG_FLOAT8(0);
01496 float8 result;
01497
01498
01499
01500
01501
01502
01503 if (arg1 == 0.0)
01504 ereport(ERROR,
01505 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
01506 errmsg("cannot take logarithm of zero")));
01507 if (arg1 < 0)
01508 ereport(ERROR,
01509 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
01510 errmsg("cannot take logarithm of a negative number")));
01511
01512 result = log10(arg1);
01513
01514 CHECKFLOATVAL(result, isinf(arg1), arg1 == 1);
01515 PG_RETURN_FLOAT8(result);
01516 }
01517
01518
01519
01520
01521
01522 Datum
01523 dacos(PG_FUNCTION_ARGS)
01524 {
01525 float8 arg1 = PG_GETARG_FLOAT8(0);
01526 float8 result;
01527
01528
01529
01530
01531
01532 errno = 0;
01533 result = acos(arg1);
01534 if (errno != 0)
01535 ereport(ERROR,
01536 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01537 errmsg("input is out of range")));
01538
01539 CHECKFLOATVAL(result, isinf(arg1), true);
01540 PG_RETURN_FLOAT8(result);
01541 }
01542
01543
01544
01545
01546
01547 Datum
01548 dasin(PG_FUNCTION_ARGS)
01549 {
01550 float8 arg1 = PG_GETARG_FLOAT8(0);
01551 float8 result;
01552
01553 errno = 0;
01554 result = asin(arg1);
01555 if (errno != 0)
01556 ereport(ERROR,
01557 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01558 errmsg("input is out of range")));
01559
01560 CHECKFLOATVAL(result, isinf(arg1), true);
01561 PG_RETURN_FLOAT8(result);
01562 }
01563
01564
01565
01566
01567
01568 Datum
01569 datan(PG_FUNCTION_ARGS)
01570 {
01571 float8 arg1 = PG_GETARG_FLOAT8(0);
01572 float8 result;
01573
01574 errno = 0;
01575 result = atan(arg1);
01576 if (errno != 0)
01577 ereport(ERROR,
01578 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01579 errmsg("input is out of range")));
01580
01581 CHECKFLOATVAL(result, isinf(arg1), true);
01582 PG_RETURN_FLOAT8(result);
01583 }
01584
01585
01586
01587
01588
01589 Datum
01590 datan2(PG_FUNCTION_ARGS)
01591 {
01592 float8 arg1 = PG_GETARG_FLOAT8(0);
01593 float8 arg2 = PG_GETARG_FLOAT8(1);
01594 float8 result;
01595
01596 errno = 0;
01597 result = atan2(arg1, arg2);
01598 if (errno != 0)
01599 ereport(ERROR,
01600 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01601 errmsg("input is out of range")));
01602
01603 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
01604 PG_RETURN_FLOAT8(result);
01605 }
01606
01607
01608
01609
01610
01611 Datum
01612 dcos(PG_FUNCTION_ARGS)
01613 {
01614 float8 arg1 = PG_GETARG_FLOAT8(0);
01615 float8 result;
01616
01617 errno = 0;
01618 result = cos(arg1);
01619 if (errno != 0)
01620 ereport(ERROR,
01621 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01622 errmsg("input is out of range")));
01623
01624 CHECKFLOATVAL(result, isinf(arg1), true);
01625 PG_RETURN_FLOAT8(result);
01626 }
01627
01628
01629
01630
01631
01632 Datum
01633 dcot(PG_FUNCTION_ARGS)
01634 {
01635 float8 arg1 = PG_GETARG_FLOAT8(0);
01636 float8 result;
01637
01638 errno = 0;
01639 result = tan(arg1);
01640 if (errno != 0)
01641 ereport(ERROR,
01642 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01643 errmsg("input is out of range")));
01644
01645 result = 1.0 / result;
01646 CHECKFLOATVAL(result, true , true);
01647 PG_RETURN_FLOAT8(result);
01648 }
01649
01650
01651
01652
01653
01654 Datum
01655 dsin(PG_FUNCTION_ARGS)
01656 {
01657 float8 arg1 = PG_GETARG_FLOAT8(0);
01658 float8 result;
01659
01660 errno = 0;
01661 result = sin(arg1);
01662 if (errno != 0)
01663 ereport(ERROR,
01664 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01665 errmsg("input is out of range")));
01666
01667 CHECKFLOATVAL(result, isinf(arg1), true);
01668 PG_RETURN_FLOAT8(result);
01669 }
01670
01671
01672
01673
01674
01675 Datum
01676 dtan(PG_FUNCTION_ARGS)
01677 {
01678 float8 arg1 = PG_GETARG_FLOAT8(0);
01679 float8 result;
01680
01681 errno = 0;
01682 result = tan(arg1);
01683 if (errno != 0)
01684 ereport(ERROR,
01685 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01686 errmsg("input is out of range")));
01687
01688 CHECKFLOATVAL(result, true , true);
01689 PG_RETURN_FLOAT8(result);
01690 }
01691
01692
01693
01694
01695
01696 Datum
01697 degrees(PG_FUNCTION_ARGS)
01698 {
01699 float8 arg1 = PG_GETARG_FLOAT8(0);
01700 float8 result;
01701
01702 result = arg1 * (180.0 / M_PI);
01703
01704 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
01705 PG_RETURN_FLOAT8(result);
01706 }
01707
01708
01709
01710
01711
01712 Datum
01713 dpi(PG_FUNCTION_ARGS)
01714 {
01715 PG_RETURN_FLOAT8(M_PI);
01716 }
01717
01718
01719
01720
01721
01722 Datum
01723 radians(PG_FUNCTION_ARGS)
01724 {
01725 float8 arg1 = PG_GETARG_FLOAT8(0);
01726 float8 result;
01727
01728 result = arg1 * (M_PI / 180.0);
01729
01730 CHECKFLOATVAL(result, isinf(arg1), arg1 == 0);
01731 PG_RETURN_FLOAT8(result);
01732 }
01733
01734
01735
01736
01737
01738 Datum
01739 drandom(PG_FUNCTION_ARGS)
01740 {
01741 float8 result;
01742
01743
01744 result = (double) random() / ((double) MAX_RANDOM_VALUE + 1);
01745
01746 PG_RETURN_FLOAT8(result);
01747 }
01748
01749
01750
01751
01752
01753 Datum
01754 setseed(PG_FUNCTION_ARGS)
01755 {
01756 float8 seed = PG_GETARG_FLOAT8(0);
01757 int iseed;
01758
01759 if (seed < -1 || seed > 1)
01760 elog(ERROR, "setseed parameter %f out of range [-1,1]", seed);
01761
01762 iseed = (int) (seed * MAX_RANDOM_VALUE);
01763 srandom((unsigned int) iseed);
01764
01765 PG_RETURN_VOID();
01766 }
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792 static float8 *
01793 check_float8_array(ArrayType *transarray, const char *caller, int n)
01794 {
01795
01796
01797
01798
01799
01800 if (ARR_NDIM(transarray) != 1 ||
01801 ARR_DIMS(transarray)[0] != n ||
01802 ARR_HASNULL(transarray) ||
01803 ARR_ELEMTYPE(transarray) != FLOAT8OID)
01804 elog(ERROR, "%s: expected %d-element float8 array", caller, n);
01805 return (float8 *) ARR_DATA_PTR(transarray);
01806 }
01807
01808 Datum
01809 float8_accum(PG_FUNCTION_ARGS)
01810 {
01811 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
01812 float8 newval = PG_GETARG_FLOAT8(1);
01813 float8 *transvalues;
01814 float8 N,
01815 sumX,
01816 sumX2;
01817
01818 transvalues = check_float8_array(transarray, "float8_accum", 3);
01819 N = transvalues[0];
01820 sumX = transvalues[1];
01821 sumX2 = transvalues[2];
01822
01823 N += 1.0;
01824 sumX += newval;
01825 CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
01826 sumX2 += newval * newval;
01827 CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
01828
01829
01830
01831
01832
01833
01834 if (AggCheckCallContext(fcinfo, NULL))
01835 {
01836 transvalues[0] = N;
01837 transvalues[1] = sumX;
01838 transvalues[2] = sumX2;
01839
01840 PG_RETURN_ARRAYTYPE_P(transarray);
01841 }
01842 else
01843 {
01844 Datum transdatums[3];
01845 ArrayType *result;
01846
01847 transdatums[0] = Float8GetDatumFast(N);
01848 transdatums[1] = Float8GetDatumFast(sumX);
01849 transdatums[2] = Float8GetDatumFast(sumX2);
01850
01851 result = construct_array(transdatums, 3,
01852 FLOAT8OID,
01853 sizeof(float8), FLOAT8PASSBYVAL, 'd');
01854
01855 PG_RETURN_ARRAYTYPE_P(result);
01856 }
01857 }
01858
01859 Datum
01860 float4_accum(PG_FUNCTION_ARGS)
01861 {
01862 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
01863
01864
01865 float8 newval = PG_GETARG_FLOAT4(1);
01866 float8 *transvalues;
01867 float8 N,
01868 sumX,
01869 sumX2;
01870
01871 transvalues = check_float8_array(transarray, "float4_accum", 3);
01872 N = transvalues[0];
01873 sumX = transvalues[1];
01874 sumX2 = transvalues[2];
01875
01876 N += 1.0;
01877 sumX += newval;
01878 CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newval), true);
01879 sumX2 += newval * newval;
01880 CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newval), true);
01881
01882
01883
01884
01885
01886
01887 if (AggCheckCallContext(fcinfo, NULL))
01888 {
01889 transvalues[0] = N;
01890 transvalues[1] = sumX;
01891 transvalues[2] = sumX2;
01892
01893 PG_RETURN_ARRAYTYPE_P(transarray);
01894 }
01895 else
01896 {
01897 Datum transdatums[3];
01898 ArrayType *result;
01899
01900 transdatums[0] = Float8GetDatumFast(N);
01901 transdatums[1] = Float8GetDatumFast(sumX);
01902 transdatums[2] = Float8GetDatumFast(sumX2);
01903
01904 result = construct_array(transdatums, 3,
01905 FLOAT8OID,
01906 sizeof(float8), FLOAT8PASSBYVAL, 'd');
01907
01908 PG_RETURN_ARRAYTYPE_P(result);
01909 }
01910 }
01911
01912 Datum
01913 float8_avg(PG_FUNCTION_ARGS)
01914 {
01915 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
01916 float8 *transvalues;
01917 float8 N,
01918 sumX;
01919
01920 transvalues = check_float8_array(transarray, "float8_avg", 3);
01921 N = transvalues[0];
01922 sumX = transvalues[1];
01923
01924
01925
01926 if (N == 0.0)
01927 PG_RETURN_NULL();
01928
01929 PG_RETURN_FLOAT8(sumX / N);
01930 }
01931
01932 Datum
01933 float8_var_pop(PG_FUNCTION_ARGS)
01934 {
01935 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
01936 float8 *transvalues;
01937 float8 N,
01938 sumX,
01939 sumX2,
01940 numerator;
01941
01942 transvalues = check_float8_array(transarray, "float8_var_pop", 3);
01943 N = transvalues[0];
01944 sumX = transvalues[1];
01945 sumX2 = transvalues[2];
01946
01947
01948 if (N == 0.0)
01949 PG_RETURN_NULL();
01950
01951 numerator = N * sumX2 - sumX * sumX;
01952 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
01953
01954
01955 if (numerator <= 0.0)
01956 PG_RETURN_FLOAT8(0.0);
01957
01958 PG_RETURN_FLOAT8(numerator / (N * N));
01959 }
01960
01961 Datum
01962 float8_var_samp(PG_FUNCTION_ARGS)
01963 {
01964 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
01965 float8 *transvalues;
01966 float8 N,
01967 sumX,
01968 sumX2,
01969 numerator;
01970
01971 transvalues = check_float8_array(transarray, "float8_var_samp", 3);
01972 N = transvalues[0];
01973 sumX = transvalues[1];
01974 sumX2 = transvalues[2];
01975
01976
01977 if (N <= 1.0)
01978 PG_RETURN_NULL();
01979
01980 numerator = N * sumX2 - sumX * sumX;
01981 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
01982
01983
01984 if (numerator <= 0.0)
01985 PG_RETURN_FLOAT8(0.0);
01986
01987 PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
01988 }
01989
01990 Datum
01991 float8_stddev_pop(PG_FUNCTION_ARGS)
01992 {
01993 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
01994 float8 *transvalues;
01995 float8 N,
01996 sumX,
01997 sumX2,
01998 numerator;
01999
02000 transvalues = check_float8_array(transarray, "float8_stddev_pop", 3);
02001 N = transvalues[0];
02002 sumX = transvalues[1];
02003 sumX2 = transvalues[2];
02004
02005
02006 if (N == 0.0)
02007 PG_RETURN_NULL();
02008
02009 numerator = N * sumX2 - sumX * sumX;
02010 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
02011
02012
02013 if (numerator <= 0.0)
02014 PG_RETURN_FLOAT8(0.0);
02015
02016 PG_RETURN_FLOAT8(sqrt(numerator / (N * N)));
02017 }
02018
02019 Datum
02020 float8_stddev_samp(PG_FUNCTION_ARGS)
02021 {
02022 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02023 float8 *transvalues;
02024 float8 N,
02025 sumX,
02026 sumX2,
02027 numerator;
02028
02029 transvalues = check_float8_array(transarray, "float8_stddev_samp", 3);
02030 N = transvalues[0];
02031 sumX = transvalues[1];
02032 sumX2 = transvalues[2];
02033
02034
02035 if (N <= 1.0)
02036 PG_RETURN_NULL();
02037
02038 numerator = N * sumX2 - sumX * sumX;
02039 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
02040
02041
02042 if (numerator <= 0.0)
02043 PG_RETURN_FLOAT8(0.0);
02044
02045 PG_RETURN_FLOAT8(sqrt(numerator / (N * (N - 1.0))));
02046 }
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064 Datum
02065 float8_regr_accum(PG_FUNCTION_ARGS)
02066 {
02067 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02068 float8 newvalY = PG_GETARG_FLOAT8(1);
02069 float8 newvalX = PG_GETARG_FLOAT8(2);
02070 float8 *transvalues;
02071 float8 N,
02072 sumX,
02073 sumX2,
02074 sumY,
02075 sumY2,
02076 sumXY;
02077
02078 transvalues = check_float8_array(transarray, "float8_regr_accum", 6);
02079 N = transvalues[0];
02080 sumX = transvalues[1];
02081 sumX2 = transvalues[2];
02082 sumY = transvalues[3];
02083 sumY2 = transvalues[4];
02084 sumXY = transvalues[5];
02085
02086 N += 1.0;
02087 sumX += newvalX;
02088 CHECKFLOATVAL(sumX, isinf(transvalues[1]) || isinf(newvalX), true);
02089 sumX2 += newvalX * newvalX;
02090 CHECKFLOATVAL(sumX2, isinf(transvalues[2]) || isinf(newvalX), true);
02091 sumY += newvalY;
02092 CHECKFLOATVAL(sumY, isinf(transvalues[3]) || isinf(newvalY), true);
02093 sumY2 += newvalY * newvalY;
02094 CHECKFLOATVAL(sumY2, isinf(transvalues[4]) || isinf(newvalY), true);
02095 sumXY += newvalX * newvalY;
02096 CHECKFLOATVAL(sumXY, isinf(transvalues[5]) || isinf(newvalX) ||
02097 isinf(newvalY), true);
02098
02099
02100
02101
02102
02103
02104 if (AggCheckCallContext(fcinfo, NULL))
02105 {
02106 transvalues[0] = N;
02107 transvalues[1] = sumX;
02108 transvalues[2] = sumX2;
02109 transvalues[3] = sumY;
02110 transvalues[4] = sumY2;
02111 transvalues[5] = sumXY;
02112
02113 PG_RETURN_ARRAYTYPE_P(transarray);
02114 }
02115 else
02116 {
02117 Datum transdatums[6];
02118 ArrayType *result;
02119
02120 transdatums[0] = Float8GetDatumFast(N);
02121 transdatums[1] = Float8GetDatumFast(sumX);
02122 transdatums[2] = Float8GetDatumFast(sumX2);
02123 transdatums[3] = Float8GetDatumFast(sumY);
02124 transdatums[4] = Float8GetDatumFast(sumY2);
02125 transdatums[5] = Float8GetDatumFast(sumXY);
02126
02127 result = construct_array(transdatums, 6,
02128 FLOAT8OID,
02129 sizeof(float8), FLOAT8PASSBYVAL, 'd');
02130
02131 PG_RETURN_ARRAYTYPE_P(result);
02132 }
02133 }
02134
02135 Datum
02136 float8_regr_sxx(PG_FUNCTION_ARGS)
02137 {
02138 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02139 float8 *transvalues;
02140 float8 N,
02141 sumX,
02142 sumX2,
02143 numerator;
02144
02145 transvalues = check_float8_array(transarray, "float8_regr_sxx", 6);
02146 N = transvalues[0];
02147 sumX = transvalues[1];
02148 sumX2 = transvalues[2];
02149
02150
02151 if (N < 1.0)
02152 PG_RETURN_NULL();
02153
02154 numerator = N * sumX2 - sumX * sumX;
02155 CHECKFLOATVAL(numerator, isinf(sumX2) || isinf(sumX), true);
02156
02157
02158 if (numerator <= 0.0)
02159 PG_RETURN_FLOAT8(0.0);
02160
02161 PG_RETURN_FLOAT8(numerator / N);
02162 }
02163
02164 Datum
02165 float8_regr_syy(PG_FUNCTION_ARGS)
02166 {
02167 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02168 float8 *transvalues;
02169 float8 N,
02170 sumY,
02171 sumY2,
02172 numerator;
02173
02174 transvalues = check_float8_array(transarray, "float8_regr_syy", 6);
02175 N = transvalues[0];
02176 sumY = transvalues[3];
02177 sumY2 = transvalues[4];
02178
02179
02180 if (N < 1.0)
02181 PG_RETURN_NULL();
02182
02183 numerator = N * sumY2 - sumY * sumY;
02184 CHECKFLOATVAL(numerator, isinf(sumY2) || isinf(sumY), true);
02185
02186
02187 if (numerator <= 0.0)
02188 PG_RETURN_FLOAT8(0.0);
02189
02190 PG_RETURN_FLOAT8(numerator / N);
02191 }
02192
02193 Datum
02194 float8_regr_sxy(PG_FUNCTION_ARGS)
02195 {
02196 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02197 float8 *transvalues;
02198 float8 N,
02199 sumX,
02200 sumY,
02201 sumXY,
02202 numerator;
02203
02204 transvalues = check_float8_array(transarray, "float8_regr_sxy", 6);
02205 N = transvalues[0];
02206 sumX = transvalues[1];
02207 sumY = transvalues[3];
02208 sumXY = transvalues[5];
02209
02210
02211 if (N < 1.0)
02212 PG_RETURN_NULL();
02213
02214 numerator = N * sumXY - sumX * sumY;
02215 CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
02216 isinf(sumY), true);
02217
02218
02219
02220 PG_RETURN_FLOAT8(numerator / N);
02221 }
02222
02223 Datum
02224 float8_regr_avgx(PG_FUNCTION_ARGS)
02225 {
02226 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02227 float8 *transvalues;
02228 float8 N,
02229 sumX;
02230
02231 transvalues = check_float8_array(transarray, "float8_regr_avgx", 6);
02232 N = transvalues[0];
02233 sumX = transvalues[1];
02234
02235
02236 if (N < 1.0)
02237 PG_RETURN_NULL();
02238
02239 PG_RETURN_FLOAT8(sumX / N);
02240 }
02241
02242 Datum
02243 float8_regr_avgy(PG_FUNCTION_ARGS)
02244 {
02245 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02246 float8 *transvalues;
02247 float8 N,
02248 sumY;
02249
02250 transvalues = check_float8_array(transarray, "float8_regr_avgy", 6);
02251 N = transvalues[0];
02252 sumY = transvalues[3];
02253
02254
02255 if (N < 1.0)
02256 PG_RETURN_NULL();
02257
02258 PG_RETURN_FLOAT8(sumY / N);
02259 }
02260
02261 Datum
02262 float8_covar_pop(PG_FUNCTION_ARGS)
02263 {
02264 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02265 float8 *transvalues;
02266 float8 N,
02267 sumX,
02268 sumY,
02269 sumXY,
02270 numerator;
02271
02272 transvalues = check_float8_array(transarray, "float8_covar_pop", 6);
02273 N = transvalues[0];
02274 sumX = transvalues[1];
02275 sumY = transvalues[3];
02276 sumXY = transvalues[5];
02277
02278
02279 if (N < 1.0)
02280 PG_RETURN_NULL();
02281
02282 numerator = N * sumXY - sumX * sumY;
02283 CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
02284 isinf(sumY), true);
02285
02286 PG_RETURN_FLOAT8(numerator / (N * N));
02287 }
02288
02289 Datum
02290 float8_covar_samp(PG_FUNCTION_ARGS)
02291 {
02292 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02293 float8 *transvalues;
02294 float8 N,
02295 sumX,
02296 sumY,
02297 sumXY,
02298 numerator;
02299
02300 transvalues = check_float8_array(transarray, "float8_covar_samp", 6);
02301 N = transvalues[0];
02302 sumX = transvalues[1];
02303 sumY = transvalues[3];
02304 sumXY = transvalues[5];
02305
02306
02307 if (N < 2.0)
02308 PG_RETURN_NULL();
02309
02310 numerator = N * sumXY - sumX * sumY;
02311 CHECKFLOATVAL(numerator, isinf(sumXY) || isinf(sumX) ||
02312 isinf(sumY), true);
02313
02314 PG_RETURN_FLOAT8(numerator / (N * (N - 1.0)));
02315 }
02316
02317 Datum
02318 float8_corr(PG_FUNCTION_ARGS)
02319 {
02320 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02321 float8 *transvalues;
02322 float8 N,
02323 sumX,
02324 sumX2,
02325 sumY,
02326 sumY2,
02327 sumXY,
02328 numeratorX,
02329 numeratorY,
02330 numeratorXY;
02331
02332 transvalues = check_float8_array(transarray, "float8_corr", 6);
02333 N = transvalues[0];
02334 sumX = transvalues[1];
02335 sumX2 = transvalues[2];
02336 sumY = transvalues[3];
02337 sumY2 = transvalues[4];
02338 sumXY = transvalues[5];
02339
02340
02341 if (N < 1.0)
02342 PG_RETURN_NULL();
02343
02344 numeratorX = N * sumX2 - sumX * sumX;
02345 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
02346 numeratorY = N * sumY2 - sumY * sumY;
02347 CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
02348 numeratorXY = N * sumXY - sumX * sumY;
02349 CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
02350 isinf(sumY), true);
02351 if (numeratorX <= 0 || numeratorY <= 0)
02352 PG_RETURN_NULL();
02353
02354 PG_RETURN_FLOAT8(numeratorXY / sqrt(numeratorX * numeratorY));
02355 }
02356
02357 Datum
02358 float8_regr_r2(PG_FUNCTION_ARGS)
02359 {
02360 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02361 float8 *transvalues;
02362 float8 N,
02363 sumX,
02364 sumX2,
02365 sumY,
02366 sumY2,
02367 sumXY,
02368 numeratorX,
02369 numeratorY,
02370 numeratorXY;
02371
02372 transvalues = check_float8_array(transarray, "float8_regr_r2", 6);
02373 N = transvalues[0];
02374 sumX = transvalues[1];
02375 sumX2 = transvalues[2];
02376 sumY = transvalues[3];
02377 sumY2 = transvalues[4];
02378 sumXY = transvalues[5];
02379
02380
02381 if (N < 1.0)
02382 PG_RETURN_NULL();
02383
02384 numeratorX = N * sumX2 - sumX * sumX;
02385 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
02386 numeratorY = N * sumY2 - sumY * sumY;
02387 CHECKFLOATVAL(numeratorY, isinf(sumY2) || isinf(sumY), true);
02388 numeratorXY = N * sumXY - sumX * sumY;
02389 CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
02390 isinf(sumY), true);
02391 if (numeratorX <= 0)
02392 PG_RETURN_NULL();
02393
02394 if (numeratorY <= 0)
02395 PG_RETURN_FLOAT8(1.0);
02396
02397 PG_RETURN_FLOAT8((numeratorXY * numeratorXY) /
02398 (numeratorX * numeratorY));
02399 }
02400
02401 Datum
02402 float8_regr_slope(PG_FUNCTION_ARGS)
02403 {
02404 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02405 float8 *transvalues;
02406 float8 N,
02407 sumX,
02408 sumX2,
02409 sumY,
02410 sumXY,
02411 numeratorX,
02412 numeratorXY;
02413
02414 transvalues = check_float8_array(transarray, "float8_regr_slope", 6);
02415 N = transvalues[0];
02416 sumX = transvalues[1];
02417 sumX2 = transvalues[2];
02418 sumY = transvalues[3];
02419 sumXY = transvalues[5];
02420
02421
02422 if (N < 1.0)
02423 PG_RETURN_NULL();
02424
02425 numeratorX = N * sumX2 - sumX * sumX;
02426 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
02427 numeratorXY = N * sumXY - sumX * sumY;
02428 CHECKFLOATVAL(numeratorXY, isinf(sumXY) || isinf(sumX) ||
02429 isinf(sumY), true);
02430 if (numeratorX <= 0)
02431 PG_RETURN_NULL();
02432
02433 PG_RETURN_FLOAT8(numeratorXY / numeratorX);
02434 }
02435
02436 Datum
02437 float8_regr_intercept(PG_FUNCTION_ARGS)
02438 {
02439 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
02440 float8 *transvalues;
02441 float8 N,
02442 sumX,
02443 sumX2,
02444 sumY,
02445 sumXY,
02446 numeratorX,
02447 numeratorXXY;
02448
02449 transvalues = check_float8_array(transarray, "float8_regr_intercept", 6);
02450 N = transvalues[0];
02451 sumX = transvalues[1];
02452 sumX2 = transvalues[2];
02453 sumY = transvalues[3];
02454 sumXY = transvalues[5];
02455
02456
02457 if (N < 1.0)
02458 PG_RETURN_NULL();
02459
02460 numeratorX = N * sumX2 - sumX * sumX;
02461 CHECKFLOATVAL(numeratorX, isinf(sumX2) || isinf(sumX), true);
02462 numeratorXXY = sumY * sumX2 - sumX * sumXY;
02463 CHECKFLOATVAL(numeratorXXY, isinf(sumY) || isinf(sumX2) ||
02464 isinf(sumX) || isinf(sumXY), true);
02465 if (numeratorX <= 0)
02466 PG_RETURN_NULL();
02467
02468 PG_RETURN_FLOAT8(numeratorXXY / numeratorX);
02469 }
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484 Datum
02485 float48pl(PG_FUNCTION_ARGS)
02486 {
02487 float4 arg1 = PG_GETARG_FLOAT4(0);
02488 float8 arg2 = PG_GETARG_FLOAT8(1);
02489 float8 result;
02490
02491 result = arg1 + arg2;
02492 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
02493 PG_RETURN_FLOAT8(result);
02494 }
02495
02496 Datum
02497 float48mi(PG_FUNCTION_ARGS)
02498 {
02499 float4 arg1 = PG_GETARG_FLOAT4(0);
02500 float8 arg2 = PG_GETARG_FLOAT8(1);
02501 float8 result;
02502
02503 result = arg1 - arg2;
02504 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
02505 PG_RETURN_FLOAT8(result);
02506 }
02507
02508 Datum
02509 float48mul(PG_FUNCTION_ARGS)
02510 {
02511 float4 arg1 = PG_GETARG_FLOAT4(0);
02512 float8 arg2 = PG_GETARG_FLOAT8(1);
02513 float8 result;
02514
02515 result = arg1 * arg2;
02516 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
02517 arg1 == 0 || arg2 == 0);
02518 PG_RETURN_FLOAT8(result);
02519 }
02520
02521 Datum
02522 float48div(PG_FUNCTION_ARGS)
02523 {
02524 float4 arg1 = PG_GETARG_FLOAT4(0);
02525 float8 arg2 = PG_GETARG_FLOAT8(1);
02526 float8 result;
02527
02528 if (arg2 == 0.0)
02529 ereport(ERROR,
02530 (errcode(ERRCODE_DIVISION_BY_ZERO),
02531 errmsg("division by zero")));
02532
02533 result = arg1 / arg2;
02534 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
02535 PG_RETURN_FLOAT8(result);
02536 }
02537
02538
02539
02540
02541
02542
02543
02544 Datum
02545 float84pl(PG_FUNCTION_ARGS)
02546 {
02547 float8 arg1 = PG_GETARG_FLOAT8(0);
02548 float4 arg2 = PG_GETARG_FLOAT4(1);
02549 float8 result;
02550
02551 result = arg1 + arg2;
02552
02553 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
02554 PG_RETURN_FLOAT8(result);
02555 }
02556
02557 Datum
02558 float84mi(PG_FUNCTION_ARGS)
02559 {
02560 float8 arg1 = PG_GETARG_FLOAT8(0);
02561 float4 arg2 = PG_GETARG_FLOAT4(1);
02562 float8 result;
02563
02564 result = arg1 - arg2;
02565
02566 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
02567 PG_RETURN_FLOAT8(result);
02568 }
02569
02570 Datum
02571 float84mul(PG_FUNCTION_ARGS)
02572 {
02573 float8 arg1 = PG_GETARG_FLOAT8(0);
02574 float4 arg2 = PG_GETARG_FLOAT4(1);
02575 float8 result;
02576
02577 result = arg1 * arg2;
02578
02579 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
02580 arg1 == 0 || arg2 == 0);
02581 PG_RETURN_FLOAT8(result);
02582 }
02583
02584 Datum
02585 float84div(PG_FUNCTION_ARGS)
02586 {
02587 float8 arg1 = PG_GETARG_FLOAT8(0);
02588 float4 arg2 = PG_GETARG_FLOAT4(1);
02589 float8 result;
02590
02591 if (arg2 == 0.0)
02592 ereport(ERROR,
02593 (errcode(ERRCODE_DIVISION_BY_ZERO),
02594 errmsg("division by zero")));
02595
02596 result = arg1 / arg2;
02597
02598 CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0);
02599 PG_RETURN_FLOAT8(result);
02600 }
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611 Datum
02612 float48eq(PG_FUNCTION_ARGS)
02613 {
02614 float4 arg1 = PG_GETARG_FLOAT4(0);
02615 float8 arg2 = PG_GETARG_FLOAT8(1);
02616
02617 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
02618 }
02619
02620 Datum
02621 float48ne(PG_FUNCTION_ARGS)
02622 {
02623 float4 arg1 = PG_GETARG_FLOAT4(0);
02624 float8 arg2 = PG_GETARG_FLOAT8(1);
02625
02626 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
02627 }
02628
02629 Datum
02630 float48lt(PG_FUNCTION_ARGS)
02631 {
02632 float4 arg1 = PG_GETARG_FLOAT4(0);
02633 float8 arg2 = PG_GETARG_FLOAT8(1);
02634
02635 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
02636 }
02637
02638 Datum
02639 float48le(PG_FUNCTION_ARGS)
02640 {
02641 float4 arg1 = PG_GETARG_FLOAT4(0);
02642 float8 arg2 = PG_GETARG_FLOAT8(1);
02643
02644 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
02645 }
02646
02647 Datum
02648 float48gt(PG_FUNCTION_ARGS)
02649 {
02650 float4 arg1 = PG_GETARG_FLOAT4(0);
02651 float8 arg2 = PG_GETARG_FLOAT8(1);
02652
02653 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
02654 }
02655
02656 Datum
02657 float48ge(PG_FUNCTION_ARGS)
02658 {
02659 float4 arg1 = PG_GETARG_FLOAT4(0);
02660 float8 arg2 = PG_GETARG_FLOAT8(1);
02661
02662 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
02663 }
02664
02665
02666
02667
02668 Datum
02669 float84eq(PG_FUNCTION_ARGS)
02670 {
02671 float8 arg1 = PG_GETARG_FLOAT8(0);
02672 float4 arg2 = PG_GETARG_FLOAT4(1);
02673
02674 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
02675 }
02676
02677 Datum
02678 float84ne(PG_FUNCTION_ARGS)
02679 {
02680 float8 arg1 = PG_GETARG_FLOAT8(0);
02681 float4 arg2 = PG_GETARG_FLOAT4(1);
02682
02683 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
02684 }
02685
02686 Datum
02687 float84lt(PG_FUNCTION_ARGS)
02688 {
02689 float8 arg1 = PG_GETARG_FLOAT8(0);
02690 float4 arg2 = PG_GETARG_FLOAT4(1);
02691
02692 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
02693 }
02694
02695 Datum
02696 float84le(PG_FUNCTION_ARGS)
02697 {
02698 float8 arg1 = PG_GETARG_FLOAT8(0);
02699 float4 arg2 = PG_GETARG_FLOAT4(1);
02700
02701 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
02702 }
02703
02704 Datum
02705 float84gt(PG_FUNCTION_ARGS)
02706 {
02707 float8 arg1 = PG_GETARG_FLOAT8(0);
02708 float4 arg2 = PG_GETARG_FLOAT4(1);
02709
02710 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
02711 }
02712
02713 Datum
02714 float84ge(PG_FUNCTION_ARGS)
02715 {
02716 float8 arg1 = PG_GETARG_FLOAT8(0);
02717 float4 arg2 = PG_GETARG_FLOAT4(1);
02718
02719 PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
02720 }
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736 Datum
02737 width_bucket_float8(PG_FUNCTION_ARGS)
02738 {
02739 float8 operand = PG_GETARG_FLOAT8(0);
02740 float8 bound1 = PG_GETARG_FLOAT8(1);
02741 float8 bound2 = PG_GETARG_FLOAT8(2);
02742 int32 count = PG_GETARG_INT32(3);
02743 int32 result;
02744
02745 if (count <= 0.0)
02746 ereport(ERROR,
02747 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
02748 errmsg("count must be greater than zero")));
02749
02750 if (isnan(operand) || isnan(bound1) || isnan(bound2))
02751 ereport(ERROR,
02752 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
02753 errmsg("operand, lower bound, and upper bound cannot be NaN")));
02754
02755
02756 if (isinf(bound1) || isinf(bound2))
02757 ereport(ERROR,
02758 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
02759 errmsg("lower and upper bounds must be finite")));
02760
02761 if (bound1 < bound2)
02762 {
02763 if (operand < bound1)
02764 result = 0;
02765 else if (operand >= bound2)
02766 {
02767 result = count + 1;
02768
02769 if (result < count)
02770 ereport(ERROR,
02771 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
02772 errmsg("integer out of range")));
02773 }
02774 else
02775 result = ((float8) count * (operand - bound1) / (bound2 - bound1)) + 1;
02776 }
02777 else if (bound1 > bound2)
02778 {
02779 if (operand > bound1)
02780 result = 0;
02781 else if (operand <= bound2)
02782 {
02783 result = count + 1;
02784
02785 if (result < count)
02786 ereport(ERROR,
02787 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
02788 errmsg("integer out of range")));
02789 }
02790 else
02791 result = ((float8) count * (bound1 - operand) / (bound1 - bound2)) + 1;
02792 }
02793 else
02794 {
02795 ereport(ERROR,
02796 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
02797 errmsg("lower bound cannot equal upper bound")));
02798 result = 0;
02799 }
02800
02801 PG_RETURN_INT32(result);
02802 }
02803
02804
02805
02806 #ifndef HAVE_CBRT
02807
02808 static double
02809 cbrt(double x)
02810 {
02811 int isneg = (x < 0.0);
02812 double absx = fabs(x);
02813 double tmpres = pow(absx, (double) 1.0 / (double) 3.0);
02814
02815
02816
02817
02818
02819
02820
02821 if (tmpres > 0.0)
02822 tmpres -= (tmpres - absx / (tmpres * tmpres)) / (double) 3.0;
02823
02824 return isneg ? -tmpres : tmpres;
02825 }
02826
02827 #endif