]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/float.c
Add:
[postgresql] / src / backend / utils / adt / float.c
1 /*-------------------------------------------------------------------------
2  *
3  * float.c
4  *        Functions for the built-in floating-point types.
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.53 2000/01/26 05:57:14 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  * OLD COMMENTS
17  *              Basic float4 ops:
18  *               float4in, float4out, float4abs, float4um
19  *              Basic float8 ops:
20  *               float8in, float8inAd, float8out, float8outAd, float8abs, float8um
21  *              Arithmetic operators:
22  *               float4pl, float4mi, float4mul, float4div
23  *               float8pl, float8mi, float8mul, float8div
24  *              Comparison operators:
25  *               float4eq, float4ne, float4lt, float4le, float4gt, float4ge
26  *               float8eq, float8ne, float8lt, float8le, float8gt, float8ge
27  *              Conversion routines:
28  *               ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
29  *
30  *              Random float8 ops:
31  *               dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
32  *              Arithmetic operators:
33  *               float48pl, float48mi, float48mul, float48div
34  *               float84pl, float84mi, float84mul, float84div
35  *              Comparison operators:
36  *               float48eq, float48ne, float48lt, float48le, float48gt, float48ge
37  *               float84eq, float84ne, float84lt, float84le, float84gt, float84ge
38  *
39  *              (You can do the arithmetic and comparison stuff using conversion
40  *               routines, but then you pay the overhead of converting...)
41  *
42  * XXX GLUESOME STUFF. FIX IT! -AY '94
43  *
44  *              Added some additional conversion routines and cleaned up
45  *               a bit of the existing code. Need to change the error checking
46  *               for calls to pow(), exp() since on some machines (my Linux box
47  *               included) these routines do not set errno. - tgl 97/05/10
48  */
49 #include <ctype.h>
50 #include <errno.h>
51
52 #include <float.h>                              /* faked on sunos4 */
53
54 #include <math.h>
55
56 #include "postgres.h"
57 #ifdef HAVE_LIMITS_H
58 #include <limits.h>
59 #ifndef MAXINT
60 #define MAXINT            INT_MAX
61 #endif
62 #else
63 #ifdef HAVE_VALUES_H
64 #include <values.h>
65 #endif
66 #endif
67 #include "fmgr.h"
68 #include "utils/builtins.h"
69
70 #ifndef NAN
71 #define NAN             (0.0/0.0)
72 #endif
73
74 #ifndef SHRT_MAX
75 #define SHRT_MAX 32767
76 #endif
77 #ifndef SHRT_MIN
78 #define SHRT_MIN (-32768)
79 #endif
80
81 #define FORMAT                  'g'             /* use "g" output format as standard
82                                                                  * format */
83 /* not sure what the following should be, but better to make it over-sufficient */
84 #define MAXFLOATWIDTH   64
85 #define MAXDOUBLEWIDTH  128
86
87 #if !(NeXT && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_2)
88  /* NS3.3 has conflicting declarations of these in <math.h> */
89
90 #ifndef atof
91 extern double atof(const char *p);
92
93 #endif
94
95 #ifndef HAVE_CBRT
96 #define cbrt my_cbrt
97 static double cbrt(double x);
98
99 #else
100 #if !defined(nextstep)
101 extern double cbrt(double x);
102
103 #endif
104 #endif
105
106 #ifndef HAVE_RINT
107 #define rint my_rint
108 static double rint(double x);
109
110 #else
111 extern double rint(double x);
112
113 #endif
114
115 #endif
116
117 /* ========== USER I/O ROUTINES ========== */
118
119
120 #define FLOAT4_MAX               FLT_MAX
121 #define FLOAT4_MIN               FLT_MIN
122 #define FLOAT8_MAX               DBL_MAX
123 #define FLOAT8_MIN               DBL_MIN
124
125 /*
126  * if FLOAT8_MIN and FLOAT8_MAX are the limits of the range a
127  * double can store, then how are we ever going to wind up
128  * with something stored in a double that is outside those
129  * limits?      (and similarly for FLOAT4_{MIN,MAX}/float.)
130  * doesn't make sense to me, and it causes a
131  * floating point exception on linuxalpha, so UNSAFE_FLOATS
132  * it is.
133  * (maybe someone wanted to allow for values other than DBL_MIN/
134  * DBL_MAX for FLOAT8_MIN/FLOAT8_MAX?)
135  *                                                              --djm 12/12/96
136  * according to Richard Henderson this is a known bug in gcc on
137  * the Alpha.  might as well leave the workaround in
138  * until the distributions are updated.
139  *                                                              --djm 12/16/96
140  */
141 #if ( defined(linux) && defined(__alpha__) ) && !defined(UNSAFE_FLOATS)
142 #define UNSAFE_FLOATS
143 #endif
144
145 /*
146    check to see if a float4 val is outside of
147    the FLOAT4_MIN, FLOAT4_MAX bounds.
148
149    raise an elog warning if it is
150 */
151 static void
152 CheckFloat4Val(double val)
153 {
154
155         /*
156          * defining unsafe floats's will make float4 and float8 ops faster at
157          * the cost of safety, of course!
158          */
159 #ifdef UNSAFE_FLOATS
160         return;
161 #else
162         if (fabs(val) > FLOAT4_MAX)
163                 elog(ERROR, "Bad float4 input format -- overflow");
164         if (val != 0.0 && fabs(val) < FLOAT4_MIN)
165                 elog(ERROR, "Bad float4 input format -- underflow");
166         return;
167 #endif   /* UNSAFE_FLOATS */
168 }
169
170 /*
171    check to see if a float8 val is outside of
172    the FLOAT8_MIN, FLOAT8_MAX bounds.
173
174    raise an elog warning if it is
175 */
176 void
177 CheckFloat8Val(double val)
178 {
179
180         /*
181          * defining unsafe floats's will make float4 and float8 ops faster at
182          * the cost of safety, of course!
183          */
184 #ifdef UNSAFE_FLOATS
185         return;
186 #else
187         if (fabs(val) > FLOAT8_MAX)
188                 elog(ERROR, "Bad float8 input format -- overflow");
189         if (val != 0.0 && fabs(val) < FLOAT8_MIN)
190                 elog(ERROR, "Bad float8 input format -- underflow");
191         return;
192 #endif   /* UNSAFE_FLOATS */
193 }
194
195 /*
196  *              float4in                - converts "num" to float
197  *                                                restricted syntax:
198  *                                                {<sp>} [+|-] {digit} [.{digit}] [<exp>]
199  *                                                where <sp> is a space, digit is 0-9,
200  *                                                <exp> is "e" or "E" followed by an integer.
201  */
202 float32
203 float4in(char *num)
204 {
205         float32         result = (float32) palloc(sizeof(float32data));
206         double          val;
207         char       *endptr;
208
209         errno = 0;
210         val = strtod(num, &endptr);
211         if (*endptr != '\0')
212         {
213                 /* Should we accept "NaN" or "Infinity" for float4? */
214                 elog(ERROR, "Bad float4 input format '%s'", num);
215         }
216         else
217         {
218                 if (errno == ERANGE)
219                         elog(ERROR, "Input '%s' is out of range for float4", num);
220         }
221
222         /*
223          * if we get here, we have a legal double, still need to check to see
224          * if it's a legal float
225          */
226
227         CheckFloat4Val(val);
228
229         *result = val;
230         return result;
231 }
232
233 /*
234  *              float4out               - converts a float4 number to a string
235  *                                                using a standard output format
236  */
237 char *
238 float4out(float32 num)
239 {
240         char       *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
241
242         if (!num)
243                 return strcpy(ascii, "(null)");
244
245         sprintf(ascii, "%.*g", FLT_DIG, *num);
246         return ascii;
247 }
248
249
250 /*
251  *              float8in                - converts "num" to float8
252  *                                                restricted syntax:
253  *                                                {<sp>} [+|-] {digit} [.{digit}] [<exp>]
254  *                                                where <sp> is a space, digit is 0-9,
255  *                                                <exp> is "e" or "E" followed by an integer.
256  */
257 float64
258 float8in(char *num)
259 {
260         float64         result = (float64) palloc(sizeof(float64data));
261         double          val;
262         char       *endptr;
263
264         errno = 0;
265         val = strtod(num, &endptr);
266         if (*endptr != '\0')
267         {
268                 if (strcasecmp(num, "NaN") == 0)
269                         val = NAN;
270                 else if (strcasecmp(num, "Infinity") == 0)
271                         val = HUGE_VAL;
272                 else
273                         elog(ERROR, "Bad float8 input format '%s'", num);
274         }
275         else
276         {
277                 if (errno == ERANGE)
278                         elog(ERROR, "Input '%s' is out of range for float8", num);
279         }
280
281         CheckFloat8Val(val);
282
283         *result = val;
284         return result;
285 }
286
287
288 /*
289  *              float8out               - converts float8 number to a string
290  *                                                using a standard output format
291  */
292 char *
293 float8out(float64 num)
294 {
295         char       *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
296
297         if (!num)
298                 return strcpy(ascii, "(null)");
299
300         if (isnan(*num))
301                 return strcpy(ascii, "NaN");
302         if (isinf(*num))
303                 return strcpy(ascii, "Infinity");
304
305         sprintf(ascii, "%.*g", DBL_DIG, *num);
306         return ascii;
307 }
308
309 /* ========== PUBLIC ROUTINES ========== */
310
311
312 /*
313  *              ======================
314  *              FLOAT4 BASE OPERATIONS
315  *              ======================
316  */
317
318 /*
319  *              float4abs               - returns a pointer to |arg1| (absolute value)
320  */
321 float32
322 float4abs(float32 arg1)
323 {
324         float32         result;
325         double          val;
326
327         if (!arg1)
328                 return (float32) NULL;
329
330         val = fabs(*arg1);
331
332         CheckFloat4Val(val);
333
334         result = (float32) palloc(sizeof(float32data));
335         *result = val;
336         return result;
337 }
338
339 /*
340  *              float4um                - returns a pointer to -arg1 (unary minus)
341  */
342 float32
343 float4um(float32 arg1)
344 {
345         float32         result;
346         double          val;
347
348         if (!arg1)
349                 return (float32) NULL;
350
351         val = ((*arg1 != 0) ? -(*arg1) : *arg1);
352         CheckFloat4Val(val);
353
354         result = (float32) palloc(sizeof(float32data));
355         *result = val;
356         return result;
357 }
358
359 float32
360 float4larger(float32 arg1, float32 arg2)
361 {
362         float32         result;
363
364         if (!arg1 || !arg2)
365                 return (float32) NULL;
366
367         result = (float32) palloc(sizeof(float32data));
368
369         *result = ((*arg1 > *arg2) ? *arg1 : *arg2);
370         return result;
371 }
372
373 float32
374 float4smaller(float32 arg1, float32 arg2)
375 {
376         float32         result;
377
378         if (!arg1 || !arg2)
379                 return (float32) NULL;
380
381         result = (float32) palloc(sizeof(float32data));
382
383         *result = ((*arg1 > *arg2) ? *arg2 : *arg1);
384         return result;
385 }
386
387 /*
388  *              ======================
389  *              FLOAT8 BASE OPERATIONS
390  *              ======================
391  */
392
393 /*
394  *              float8abs               - returns a pointer to |arg1| (absolute value)
395  */
396 float64
397 float8abs(float64 arg1)
398 {
399         float64         result;
400         double          val;
401
402         if (!arg1)
403                 return (float64) NULL;
404
405         result = (float64) palloc(sizeof(float64data));
406
407         val = fabs(*arg1);
408         CheckFloat8Val(val);
409         *result = val;
410         return result;
411 }
412
413
414 /*
415  *              float8um                - returns a pointer to -arg1 (unary minus)
416  */
417 float64
418 float8um(float64 arg1)
419 {
420         float64         result;
421         double          val;
422
423         if (!arg1)
424                 return (float64) NULL;
425
426         val = ((*arg1 != 0) ? -(*arg1) : *arg1);
427
428         CheckFloat8Val(val);
429         result = (float64) palloc(sizeof(float64data));
430         *result = val;
431         return result;
432 }
433
434 float64
435 float8larger(float64 arg1, float64 arg2)
436 {
437         float64         result;
438
439         if (!arg1 || !arg2)
440                 return (float64) NULL;
441
442         result = (float64) palloc(sizeof(float64data));
443
444         *result = ((*arg1 > *arg2) ? *arg1 : *arg2);
445         return result;
446 }
447
448 float64
449 float8smaller(float64 arg1, float64 arg2)
450 {
451         float64         result;
452
453         if (!arg1 || !arg2)
454                 return (float64) NULL;
455
456         result = (float64) palloc(sizeof(float64data));
457
458         *result = ((*arg1 > *arg2) ? *arg2 : *arg1);
459         return result;
460 }
461
462
463 /*
464  *              ====================
465  *              ARITHMETIC OPERATORS
466  *              ====================
467  */
468
469 /*
470  *              float4pl                - returns a pointer to arg1 + arg2
471  *              float4mi                - returns a pointer to arg1 - arg2
472  *              float4mul               - returns a pointer to arg1 * arg2
473  *              float4div               - returns a pointer to arg1 / arg2
474  *              float4inc               - returns a poniter to arg1 + 1.0
475  */
476 float32
477 float4pl(float32 arg1, float32 arg2)
478 {
479         float32         result;
480         double          val;
481
482         if (!arg1 || !arg2)
483                 return (float32) NULL;
484
485         val = *arg1 + *arg2;
486         CheckFloat4Val(val);
487
488         result = (float32) palloc(sizeof(float32data));
489         *result = val;
490
491         return result;
492 }
493
494 float32
495 float4mi(float32 arg1, float32 arg2)
496 {
497         float32         result;
498         double          val;
499
500         if (!arg1 || !arg2)
501                 return (float32) NULL;
502
503         val = *arg1 - *arg2;
504
505         CheckFloat4Val(val);
506         result = (float32) palloc(sizeof(float32data));
507         *result = val;
508         return result;
509 }
510
511 float32
512 float4mul(float32 arg1, float32 arg2)
513 {
514         float32         result;
515         double          val;
516
517         if (!arg1 || !arg2)
518                 return (float32) NULL;
519
520         val = *arg1 * *arg2;
521
522         CheckFloat4Val(val);
523         result = (float32) palloc(sizeof(float32data));
524         *result = val;
525         return result;
526 }
527
528 float32
529 float4div(float32 arg1, float32 arg2)
530 {
531         float32         result;
532         double          val;
533
534         if (!arg1 || !arg2)
535                 return (float32) NULL;
536
537         if (*arg2 == 0.0)
538                 elog(ERROR, "float4div: divide by zero error");
539
540         val = *arg1 / *arg2;
541
542         CheckFloat4Val(val);
543         result = (float32) palloc(sizeof(float32data));
544         *result = val;
545         return result;
546 }
547
548 float32
549 float4inc(float32 arg1)
550 {
551         float32         result;
552         double          val;
553
554         if (!arg1)
555                 return (float32) NULL;
556
557         val = *arg1 + (float32data) 1.0;
558
559         CheckFloat4Val(val);
560         result = (float32) palloc(sizeof(float32data));
561         *result = val;
562         return result;
563 }
564
565 /*
566  *              float8pl                - returns a pointer to arg1 + arg2
567  *              float8mi                - returns a pointer to arg1 - arg2
568  *              float8mul               - returns a pointer to arg1 * arg2
569  *              float8div               - returns a pointer to arg1 / arg2
570  *              float8inc               - returns a pointer to arg1 + 1.0
571  */
572 float64
573 float8pl(float64 arg1, float64 arg2)
574 {
575         float64         result;
576         double          val;
577
578         if (!arg1 || !arg2)
579                 return (float64) NULL;
580
581         result = (float64) palloc(sizeof(float64data));
582
583         val = *arg1 + *arg2;
584         CheckFloat8Val(val);
585         *result = val;
586         return result;
587 }
588
589 float64
590 float8mi(float64 arg1, float64 arg2)
591 {
592         float64         result;
593         double          val;
594
595         if (!arg1 || !arg2)
596                 return (float64) NULL;
597
598         result = (float64) palloc(sizeof(float64data));
599
600         val = *arg1 - *arg2;
601         CheckFloat8Val(val);
602         *result = val;
603         return result;
604 }
605
606 float64
607 float8mul(float64 arg1, float64 arg2)
608 {
609         float64         result;
610         double          val;
611
612         if (!arg1 || !arg2)
613                 return (float64) NULL;
614
615         result = (float64) palloc(sizeof(float64data));
616
617         val = *arg1 * *arg2;
618         CheckFloat8Val(val);
619         *result = val;
620         return result;
621 }
622
623 float64
624 float8div(float64 arg1, float64 arg2)
625 {
626         float64         result;
627         double          val;
628
629         if (!arg1 || !arg2)
630                 return (float64) NULL;
631
632         result = (float64) palloc(sizeof(float64data));
633
634         if (*arg2 == 0.0)
635                 elog(ERROR, "float8div: divide by zero error");
636
637         val = *arg1 / *arg2;
638         CheckFloat8Val(val);
639         *result = val;
640         return result;
641 }
642
643 float64
644 float8inc(float64 arg1)
645 {
646         float64         result;
647         double          val;
648
649         if (!arg1)
650                 return (float64) NULL;
651
652         val = *arg1 + (float64data) 1.0;
653         CheckFloat8Val(val);
654         result = (float64) palloc(sizeof(float64data));
655         *result = val;
656         return result;
657 }
658
659
660 /*
661  *              ====================
662  *              COMPARISON OPERATORS
663  *              ====================
664  */
665
666 /*
667  *              float4{eq,ne,lt,le,gt,ge}               - float4/float4 comparison operations
668  */
669 bool
670 float4eq(float32 arg1, float32 arg2)
671 {
672         if (!arg1 || !arg2)
673                 return 0;
674
675         return *arg1 == *arg2;
676 }
677
678 bool
679 float4ne(float32 arg1, float32 arg2)
680 {
681         if (!arg1 || !arg2)
682                 return 0;
683
684         return *arg1 != *arg2;
685 }
686
687 bool
688 float4lt(float32 arg1, float32 arg2)
689 {
690         if (!arg1 || !arg2)
691                 return 0;
692
693         return *arg1 < *arg2;
694 }
695
696 bool
697 float4le(float32 arg1, float32 arg2)
698 {
699         if (!arg1 || !arg2)
700                 return 0;
701
702         return *arg1 <= *arg2;
703 }
704
705 bool
706 float4gt(float32 arg1, float32 arg2)
707 {
708         if (!arg1 || !arg2)
709                 return 0;
710
711         return *arg1 > *arg2;
712 }
713
714 bool
715 float4ge(float32 arg1, float32 arg2)
716 {
717         if (!arg1 || !arg2)
718                 return 0;
719
720         return *arg1 >= *arg2;
721 }
722
723 /*
724  *              float8{eq,ne,lt,le,gt,ge}               - float8/float8 comparison operations
725  */
726 bool
727 float8eq(float64 arg1, float64 arg2)
728 {
729         if (!arg1 || !arg2)
730                 return 0;
731
732         return *arg1 == *arg2;
733 }
734
735 bool
736 float8ne(float64 arg1, float64 arg2)
737 {
738         if (!arg1 || !arg2)
739                 return 0;
740
741         return *arg1 != *arg2;
742 }
743
744 bool
745 float8lt(float64 arg1, float64 arg2)
746 {
747         if (!arg1 || !arg2)
748                 return 0;
749
750         return *arg1 < *arg2;
751 }
752
753 bool
754 float8le(float64 arg1, float64 arg2)
755 {
756         if (!arg1 || !arg2)
757                 return 0;
758
759         return *arg1 <= *arg2;
760 }
761
762 bool
763 float8gt(float64 arg1, float64 arg2)
764 {
765         if (!arg1 || !arg2)
766                 return 0;
767
768         return *arg1 > *arg2;
769 }
770
771 bool
772 float8ge(float64 arg1, float64 arg2)
773 {
774         if (!arg1 || !arg2)
775                 return 0;
776
777         return *arg1 >= *arg2;
778 }
779
780
781 /*
782  *              ===================
783  *              CONVERSION ROUTINES
784  *              ===================
785  */
786
787 /*
788  *              ftod                    - converts a float4 number to a float8 number
789  */
790 float64
791 ftod(float32 num)
792 {
793         float64         result;
794
795         if (!num)
796                 return (float64) NULL;
797
798         result = (float64) palloc(sizeof(float64data));
799
800         *result = *num;
801         return result;
802 }
803
804
805 /*
806  *              dtof                    - converts a float8 number to a float4 number
807  */
808 float32
809 dtof(float64 num)
810 {
811         float32         result;
812
813         if (!num)
814                 return (float32) NULL;
815
816         CheckFloat4Val(*num);
817
818         result = (float32) palloc(sizeof(float32data));
819
820         *result = *num;
821         return result;
822 }
823
824
825 /*
826  *              dtoi4                   - converts a float8 number to an int4 number
827  */
828 int32
829 dtoi4(float64 num)
830 {
831         int32           result;
832
833         if (!PointerIsValid(num))
834                 elog(ERROR, "dtoi4: unable to convert null");
835
836         if ((*num < INT_MIN) || (*num > INT_MAX))
837                 elog(ERROR, "dtoi4: integer out of range");
838
839         result = rint(*num);
840         return result;
841 }
842
843
844 /*
845  *              dtoi2                   - converts a float8 number to an int2 number
846  */
847 int16
848 dtoi2(float64 num)
849 {
850         int16           result;
851
852         if (!PointerIsValid(num))
853                 elog(ERROR, "dtoi2: unable to convert null");
854
855         if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
856                 elog(ERROR, "dtoi2: integer out of range");
857
858         result = rint(*num);
859         return result;
860 }
861
862
863 /*
864  *              i4tod                   - converts an int4 number to a float8 number
865  */
866 float64
867 i4tod(int32 num)
868 {
869         float64         result;
870
871         result = (float64) palloc(sizeof(float64data));
872
873         *result = num;
874         return result;
875 }
876
877
878 /*
879  *              i2tod                   - converts an int2 number to a float8 number
880  */
881 float64
882 i2tod(int16 num)
883 {
884         float64         result;
885
886         result = (float64) palloc(sizeof(float64data));
887
888         *result = num;
889         return result;
890 }
891
892
893 /*
894  *              ftoi4                   - converts a float8 number to an int4 number
895  */
896 int32
897 ftoi4(float32 num)
898 {
899         int32           result;
900
901         if (!PointerIsValid(num))
902                 elog(ERROR, "ftoi4: unable to convert null");
903
904         if ((*num < INT_MIN) || (*num > INT_MAX))
905                 elog(ERROR, "ftoi4: integer out of range");
906
907         result = rint(*num);
908         return result;
909 }
910
911
912 /*
913  *              ftoi2                   - converts a float8 number to an int2 number
914  */
915 int16
916 ftoi2(float32 num)
917 {
918         int16           result;
919
920         if (!PointerIsValid(num))
921                 elog(ERROR, "ftoi2: unable to convert null");
922
923         if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
924                 elog(ERROR, "ftoi2: integer out of range");
925
926         result = rint(*num);
927         return result;
928 }
929
930
931 /*
932  *              i4tof                   - converts an int4 number to a float8 number
933  */
934 float32
935 i4tof(int32 num)
936 {
937         float32         result;
938
939         result = (float32) palloc(sizeof(float32data));
940
941         *result = num;
942         return result;
943 }
944
945
946 /*
947  *              i2tof                   - converts an int2 number to a float8 number
948  */
949 float32
950 i2tof(int16 num)
951 {
952         float32         result;
953
954         result = (float32) palloc(sizeof(float32data));
955
956         *result = num;
957         return result;
958 }
959
960
961 /*
962  *              float8_text             - converts a float8 number to a text string
963  */
964 text *
965 float8_text(float64 num)
966 {
967         text       *result;
968         int                     len;
969         char       *str;
970
971         str = float8out(num);
972         len = (strlen(str) + VARHDRSZ);
973
974         result = palloc(len);
975
976         VARSIZE(result) = len;
977         memmove(VARDATA(result), str, (len - VARHDRSZ));
978
979         pfree(str);
980         return result;
981 }       /* float8_text() */
982
983
984 /*
985  *              text_float8             - converts a text string to a float8 number
986  */
987 float64
988 text_float8(text *string)
989 {
990         float64         result;
991         int                     len;
992         char       *str;
993
994         len = (VARSIZE(string) - VARHDRSZ);
995         str = palloc(len + 1);
996         memmove(str, VARDATA(string), len);
997         *(str + len) = '\0';
998
999         result = float8in(str);
1000         pfree(str);
1001
1002         return result;
1003 }       /* text_float8() */
1004
1005
1006 /*
1007  *              float4_text             - converts a float4 number to a text string
1008  */
1009 text *
1010 float4_text(float32 num)
1011 {
1012         text       *result;
1013         int                     len;
1014         char       *str;
1015
1016         str = float4out(num);
1017         len = (strlen(str) + VARHDRSZ);
1018
1019         result = palloc(len);
1020
1021         VARSIZE(result) = len;
1022         memmove(VARDATA(result), str, (len - VARHDRSZ));
1023
1024         pfree(str);
1025         return result;
1026 }       /* float4_text() */
1027
1028
1029 /*
1030  *              text_float4             - converts a text string to a float4 number
1031  */
1032 float32
1033 text_float4(text *string)
1034 {
1035         float32         result;
1036         int                     len;
1037         char       *str;
1038
1039         len = (VARSIZE(string) - VARHDRSZ);
1040         str = palloc(len + 1);
1041         memmove(str, VARDATA(string), len);
1042         *(str + len) = '\0';
1043
1044         result = float4in(str);
1045         pfree(str);
1046
1047         return result;
1048 }       /* text_float4() */
1049
1050
1051 /*
1052  *              =======================
1053  *              RANDOM FLOAT8 OPERATORS
1054  *              =======================
1055  */
1056
1057 /*
1058  *              dround                  - returns a pointer to  ROUND(arg1)
1059  */
1060 float64
1061 dround(float64 arg1)
1062 {
1063         float64         result;
1064         double          tmp;
1065
1066         if (!arg1)
1067                 return (float64) NULL;
1068
1069         result = (float64) palloc(sizeof(float64data));
1070
1071         tmp = *arg1;
1072         *result = (float64data) rint(tmp);
1073         return result;
1074 }
1075
1076
1077 /*
1078  *              dtrunc                  - returns a pointer to  truncation of arg1,
1079  *                                                arg1 >= 0 ... the greatest integer as float8 less
1080  *                                                                              than or equal to arg1
1081  *                                                arg1 < 0      ... the greatest integer as float8 greater
1082  *                                                                              than or equal to arg1
1083  */
1084 float64
1085 dtrunc(float64 arg1)
1086 {
1087         float64         result;
1088         double          tmp;
1089
1090         if (!arg1)
1091                 return (float64) NULL;
1092
1093         result = (float64) palloc(sizeof(float64data));
1094
1095         tmp = *arg1;
1096         if (*arg1 >= 0)
1097                 *result = (float64data) floor(tmp);
1098         else
1099                 *result = (float64data) -(floor(-tmp));
1100         return result;
1101 }
1102
1103
1104 /*
1105  *              dsqrt                   - returns a pointer to square root of arg1
1106  */
1107 float64
1108 dsqrt(float64 arg1)
1109 {
1110         float64         result;
1111         double          tmp;
1112
1113         if (!arg1)
1114                 return (float64) NULL;
1115
1116         result = (float64) palloc(sizeof(float64data));
1117
1118         tmp = *arg1;
1119         *result = (float64data) sqrt(tmp);
1120         return result;
1121 }
1122
1123
1124 /*
1125  *              dcbrt                   - returns a pointer to cube root of arg1
1126  */
1127 float64
1128 dcbrt(float64 arg1)
1129 {
1130         float64         result;
1131         double          tmp;
1132
1133         if (!arg1)
1134                 return (float64) NULL;
1135
1136         result = (float64) palloc(sizeof(float64data));
1137
1138         tmp = *arg1;
1139         *result = (float64data) cbrt(tmp);
1140         return result;
1141 }
1142
1143
1144 /*
1145  *              dpow                    - returns a pointer to pow(arg1,arg2)
1146  */
1147 float64
1148 dpow(float64 arg1, float64 arg2)
1149 {
1150         float64         result;
1151         double          tmp1,
1152                                 tmp2;
1153
1154         if (!arg1 || !arg2)
1155                 return (float64) NULL;
1156
1157         result = (float64) palloc(sizeof(float64data));
1158
1159         tmp1 = *arg1;
1160         tmp2 = *arg2;
1161
1162         /* We must check both for errno getting set and for a NaN result,
1163          * in order to deal with the vagaries of different platforms...
1164          */
1165         errno = 0;
1166         *result = (float64data) pow(tmp1, tmp2);
1167         if (errno != 0
1168 #ifdef HAVE_FINITE
1169                 || !finite(*result)
1170 #endif
1171                 )
1172                 elog(ERROR, "pow() result is out of range");
1173
1174         CheckFloat8Val(*result);
1175         return result;
1176 }
1177
1178
1179 /*
1180  *              dexp                    - returns a pointer to the exponential function of arg1
1181  */
1182 float64
1183 dexp(float64 arg1)
1184 {
1185         float64         result;
1186         double          tmp;
1187
1188         if (!arg1)
1189                 return (float64) NULL;
1190
1191         result = (float64) palloc(sizeof(float64data));
1192
1193         tmp = *arg1;
1194
1195         /* We must check both for errno getting set and for a NaN result,
1196          * in order to deal with the vagaries of different platforms.
1197          * Also, a zero result implies unreported underflow.
1198          */
1199         errno = 0;
1200         *result = (float64data) exp(tmp);
1201         if (errno != 0 || *result == 0.0
1202 #ifdef HAVE_FINITE
1203                 || !finite(*result)
1204 #endif
1205                 )
1206                 elog(ERROR, "exp() result is out of range");
1207
1208         CheckFloat8Val(*result);
1209         return result;
1210 }
1211
1212
1213 /*
1214  *              dlog1                   - returns a pointer to the natural logarithm of arg1
1215  *                                                ("dlog" is already a logging routine...)
1216  */
1217 float64
1218 dlog1(float64 arg1)
1219 {
1220         float64         result;
1221         double          tmp;
1222
1223         if (!arg1)
1224                 return (float64) NULL;
1225
1226         result = (float64) palloc(sizeof(float64data));
1227
1228         tmp = *arg1;
1229         if (tmp == 0.0)
1230                 elog(ERROR, "can't take log of zero");
1231         if (tmp < 0)
1232                 elog(ERROR, "can't take log of a negative number");
1233         *result = (float64data) log(tmp);
1234
1235         CheckFloat8Val(*result);
1236         return result;
1237 }
1238
1239
1240 /*
1241  *              ====================
1242  *              ARITHMETIC OPERATORS
1243  *              ====================
1244  */
1245
1246 /*
1247  *              float48pl               - returns a pointer to arg1 + arg2
1248  *              float48mi               - returns a pointer to arg1 - arg2
1249  *              float48mul              - returns a pointer to arg1 * arg2
1250  *              float48div              - returns a pointer to arg1 / arg2
1251  */
1252 float64
1253 float48pl(float32 arg1, float64 arg2)
1254 {
1255         float64         result;
1256
1257         if (!arg1 || !arg2)
1258                 return (float64) NULL;
1259
1260         result = (float64) palloc(sizeof(float64data));
1261
1262         *result = *arg1 + *arg2;
1263         CheckFloat8Val(*result);
1264         return result;
1265 }
1266
1267 float64
1268 float48mi(float32 arg1, float64 arg2)
1269 {
1270         float64         result;
1271
1272         if (!arg1 || !arg2)
1273                 return (float64) NULL;
1274
1275         result = (float64) palloc(sizeof(float64data));
1276
1277         *result = *arg1 - *arg2;
1278         CheckFloat8Val(*result);
1279         return result;
1280 }
1281
1282 float64
1283 float48mul(float32 arg1, float64 arg2)
1284 {
1285         float64         result;
1286
1287         if (!arg1 || !arg2)
1288                 return (float64) NULL;
1289
1290         result = (float64) palloc(sizeof(float64data));
1291
1292         *result = *arg1 * *arg2;
1293         CheckFloat8Val(*result);
1294         return result;
1295 }
1296
1297 float64
1298 float48div(float32 arg1, float64 arg2)
1299 {
1300         float64         result;
1301
1302         if (!arg1 || !arg2)
1303                 return (float64) NULL;
1304
1305         result = (float64) palloc(sizeof(float64data));
1306
1307         if (*arg2 == 0.0)
1308                 elog(ERROR, "float48div: divide by zero");
1309
1310         *result = *arg1 / *arg2;
1311         CheckFloat8Val(*result);
1312         return result;
1313 }
1314
1315 /*
1316  *              float84pl               - returns a pointer to arg1 + arg2
1317  *              float84mi               - returns a pointer to arg1 - arg2
1318  *              float84mul              - returns a pointer to arg1 * arg2
1319  *              float84div              - returns a pointer to arg1 / arg2
1320  */
1321 float64
1322 float84pl(float64 arg1, float32 arg2)
1323 {
1324         float64         result;
1325
1326         if (!arg1 || !arg2)
1327                 return (float64) NULL;
1328
1329         result = (float64) palloc(sizeof(float64data));
1330
1331         *result = *arg1 + *arg2;
1332         CheckFloat8Val(*result);
1333         return result;
1334 }
1335
1336 float64
1337 float84mi(float64 arg1, float32 arg2)
1338 {
1339         float64         result;
1340
1341         if (!arg1 || !arg2)
1342                 return (float64) NULL;
1343
1344         result = (float64) palloc(sizeof(float64data));
1345
1346         *result = *arg1 - *arg2;
1347         CheckFloat8Val(*result);
1348         return result;
1349 }
1350
1351 float64
1352 float84mul(float64 arg1, float32 arg2)
1353 {
1354
1355         float64         result;
1356
1357         if (!arg1 || !arg2)
1358                 return (float64) NULL;
1359
1360         result = (float64) palloc(sizeof(float64data));
1361
1362         *result = *arg1 * *arg2;
1363         CheckFloat8Val(*result);
1364         return result;
1365 }
1366
1367 float64
1368 float84div(float64 arg1, float32 arg2)
1369 {
1370         float64         result;
1371
1372         if (!arg1 || !arg2)
1373                 return (float64) NULL;
1374
1375         result = (float64) palloc(sizeof(float64data));
1376
1377         if (*arg2 == 0.0)
1378                 elog(ERROR, "float48div: divide by zero");
1379
1380         *result = *arg1 / *arg2;
1381         CheckFloat8Val(*result);
1382         return result;
1383 }
1384
1385 /*
1386  *              ====================
1387  *              COMPARISON OPERATORS
1388  *              ====================
1389  */
1390
1391 /*
1392  *              float48{eq,ne,lt,le,gt,ge}              - float4/float8 comparison operations
1393  */
1394 bool
1395 float48eq(float32 arg1, float64 arg2)
1396 {
1397         if (!arg1 || !arg2)
1398                 return 0;
1399
1400         return *arg1 == *arg2;
1401 }
1402
1403 bool
1404 float48ne(float32 arg1, float64 arg2)
1405 {
1406         if (!arg1 || !arg2)
1407                 return 0;
1408
1409         return *arg1 != *arg2;
1410 }
1411
1412 bool
1413 float48lt(float32 arg1, float64 arg2)
1414 {
1415         if (!arg1 || !arg2)
1416                 return 0;
1417
1418         return *arg1 < *arg2;
1419 }
1420
1421 bool
1422 float48le(float32 arg1, float64 arg2)
1423 {
1424         if (!arg1 || !arg2)
1425                 return 0;
1426
1427         return *arg1 <= *arg2;
1428 }
1429
1430 bool
1431 float48gt(float32 arg1, float64 arg2)
1432 {
1433         if (!arg1 || !arg2)
1434                 return 0;
1435
1436         return *arg1 > *arg2;
1437 }
1438
1439 bool
1440 float48ge(float32 arg1, float64 arg2)
1441 {
1442         if (!arg1 || !arg2)
1443                 return 0;
1444
1445         return *arg1 >= *arg2;
1446 }
1447
1448 /*
1449  *              float84{eq,ne,lt,le,gt,ge}              - float4/float8 comparison operations
1450  */
1451 bool
1452 float84eq(float64 arg1, float32 arg2)
1453 {
1454         if (!arg1 || !arg2)
1455                 return 0;
1456
1457         return *arg1 == *arg2;
1458 }
1459
1460 bool
1461 float84ne(float64 arg1, float32 arg2)
1462 {
1463         if (!arg1 || !arg2)
1464                 return 0;
1465
1466         return *arg1 != *arg2;
1467 }
1468
1469 bool
1470 float84lt(float64 arg1, float32 arg2)
1471 {
1472         if (!arg1 || !arg2)
1473                 return 0;
1474
1475         return *arg1 < *arg2;
1476 }
1477
1478 bool
1479 float84le(float64 arg1, float32 arg2)
1480 {
1481         if (!arg1 || !arg2)
1482                 return 0;
1483
1484         return *arg1 <= *arg2;
1485 }
1486
1487 bool
1488 float84gt(float64 arg1, float32 arg2)
1489 {
1490         if (!arg1 || !arg2)
1491                 return 0;
1492
1493         return *arg1 > *arg2;
1494 }
1495
1496 bool
1497 float84ge(float64 arg1, float32 arg2)
1498 {
1499         if (!arg1 || !arg2)
1500                 return 0;
1501
1502         return *arg1 >= *arg2;
1503 }
1504
1505 /* ========== PRIVATE ROUTINES ========== */
1506
1507 /* From "fdlibm" @ netlib.att.com */
1508
1509 #ifndef HAVE_RINT
1510
1511 /* @(#)s_rint.c 5.1 93/09/24 */
1512 /*
1513  * ====================================================
1514  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
1515  *
1516  * Developed at SunPro, a Sun Microsystems, Inc. business.
1517  * Permission to use, copy, modify, and distribute this
1518  * software is freely granted, provided that this notice
1519  * is preserved.
1520  * ====================================================
1521  */
1522
1523 /*
1524  * rint(x)
1525  * Return x rounded to integral value according to the prevailing
1526  * rounding mode.
1527  * Method:
1528  *              Using floating addition.
1529  * Exception:
1530  *              Inexact flag raised if x not equal to rint(x).
1531  */
1532
1533 #ifdef __STDC__
1534 static const double
1535 #else
1536 static double
1537 #endif
1538                         one = 1.0,
1539                         TWO52[2] = {
1540         4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
1541         -4.50359962737049600000e+15,/* 0xC3300000, 0x00000000 */
1542 };
1543
1544 #ifdef __STDC__
1545 static double
1546 rint(double x)
1547 #else
1548 static double
1549 rint(x)
1550 double          x;
1551
1552 #endif
1553 {
1554         int                     i0,
1555                                 n0,
1556                                 j0,
1557                                 sx;
1558         unsigned        i,
1559                                 i1;
1560         double          w,
1561                                 t;
1562
1563         n0 = (*((int *) &one) >> 29) ^ 1;
1564         i0 = *(n0 + (int *) &x);
1565         sx = (i0 >> 31) & 1;
1566         i1 = *(1 - n0 + (int *) &x);
1567         j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
1568         if (j0 < 20)
1569         {
1570                 if (j0 < 0)
1571                 {
1572                         if (((i0 & 0x7fffffff) | i1) == 0)
1573                                 return x;
1574                         i1 |= (i0 & 0x0fffff);
1575                         i0 &= 0xfffe0000;
1576                         i0 |= ((i1 | -i1) >> 12) & 0x80000;
1577                         *(n0 + (int *) &x) = i0;
1578                         w = TWO52[sx] + x;
1579                         t = w - TWO52[sx];
1580                         i0 = *(n0 + (int *) &t);
1581                         *(n0 + (int *) &t) = (i0 & 0x7fffffff) | (sx << 31);
1582                         return t;
1583                 }
1584                 else
1585                 {
1586                         i = (0x000fffff) >> j0;
1587                         if (((i0 & i) | i1) == 0)
1588                                 return x;               /* x is integral */
1589                         i >>= 1;
1590                         if (((i0 & i) | i1) != 0)
1591                         {
1592                                 if (j0 == 19)
1593                                         i1 = 0x40000000;
1594                                 else
1595                                         i0 = (i0 & (~i)) | ((0x20000) >> j0);
1596                         }
1597                 }
1598         }
1599         else if (j0 > 51)
1600         {
1601                 if (j0 == 0x400)
1602                         return x + x;           /* inf or NaN */
1603                 else
1604                         return x;                       /* x is integral */
1605         }
1606         else
1607         {
1608                 i = ((unsigned) (0xffffffff)) >> (j0 - 20);
1609                 if ((i1 & i) == 0)
1610                         return x;                       /* x is integral */
1611                 i >>= 1;
1612                 if ((i1 & i) != 0)
1613                         i1 = (i1 & (~i)) | ((0x40000000) >> (j0 - 20));
1614         }
1615         *(n0 + (int *) &x) = i0;
1616         *(1 - n0 + (int *) &x) = i1;
1617         w = TWO52[sx] + x;
1618         return w - TWO52[sx];
1619 }
1620
1621 #endif   /* !HAVE_RINT */
1622
1623 #ifndef HAVE_CBRT
1624
1625 static
1626 double
1627 cbrt(x)
1628 double          x;
1629 {
1630         int                     isneg = (x < 0.0);
1631         double          tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
1632
1633         return isneg ? -tmpres : tmpres;
1634 }
1635
1636 #endif   /* !HAVE_CBRT */