]> granicus.if.org Git - postgresql/blob - src/tutorial/complex.c
pgindent run on all C files. Java run to follow. initdb/regression
[postgresql] / src / tutorial / complex.c
1 /******************************************************************************
2   This file contains routines that can be bound to a Postgres backend and
3   called by the backend in the process of processing queries.  The calling
4   format for these routines is dictated by Postgres architecture.
5 ******************************************************************************/
6
7 #include "postgres.h"
8
9 typedef struct Complex
10 {
11         double          x;
12         double          y;
13 }                       Complex;
14
15 /* These prototypes declare the requirements that Postgres places on these
16    user written functions.
17 */
18 Complex    *complex_in(char *str);
19 char       *complex_out(Complex * complex);
20 Complex    *complex_add(Complex * a, Complex * b);
21 bool            complex_abs_lt(Complex * a, Complex * b);
22 bool            complex_abs_le(Complex * a, Complex * b);
23 bool            complex_abs_eq(Complex * a, Complex * b);
24 bool            complex_abs_ge(Complex * a, Complex * b);
25 bool            complex_abs_gt(Complex * a, Complex * b);
26 int4            complex_abs_cmp(Complex * a, Complex * b);
27
28
29 /*****************************************************************************
30  * Input/Output functions
31  *****************************************************************************/
32
33 Complex *
34 complex_in(char *str)
35 {
36         double          x,
37                                 y;
38         Complex    *result;
39
40         if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
41         {
42                 elog(ERROR, "complex_in: error in parsing \"%s\"", str);
43                 return NULL;
44         }
45         result = (Complex *) palloc(sizeof(Complex));
46         result->x = x;
47         result->y = y;
48         return result;
49 }
50
51 /*
52  * You might have noticed a slight inconsistency between the following
53  * declaration and the SQL definition:
54  *         CREATE FUNCTION complex_out(opaque) RETURNS opaque ...
55  * The reason is that the argument pass into complex_out is really just a
56  * pointer. POSTGRES thinks all output functions are:
57  *         char *out_func(char *);
58  */
59 char *
60 complex_out(Complex * complex)
61 {
62         char       *result;
63
64         if (complex == NULL)
65                 return NULL;
66
67         result = (char *) palloc(60);
68         sprintf(result, "(%g,%g)", complex->x, complex->y);
69         return result;
70 }
71
72 /*****************************************************************************
73  * New Operators
74  *****************************************************************************/
75
76 Complex *
77 complex_add(Complex * a, Complex * b)
78 {
79         Complex    *result;
80
81         result = (Complex *) palloc(sizeof(Complex));
82         result->x = a->x + b->x;
83         result->y = a->y + b->y;
84         return result;
85 }
86
87
88 /*****************************************************************************
89  * Operator class for defining B-tree index
90  *****************************************************************************/
91
92 #define Mag(c)  ((c)->x*(c)->x + (c)->y*(c)->y)
93
94 bool
95 complex_abs_lt(Complex * a, Complex * b)
96 {
97         double          amag = Mag(a),
98                                 bmag = Mag(b);
99
100         return amag < bmag;
101 }
102
103 bool
104 complex_abs_le(Complex * a, Complex * b)
105 {
106         double          amag = Mag(a),
107                                 bmag = Mag(b);
108
109         return amag <= bmag;
110 }
111
112 bool
113 complex_abs_eq(Complex * a, Complex * b)
114 {
115         double          amag = Mag(a),
116                                 bmag = Mag(b);
117
118         return amag == bmag;
119 }
120
121 bool
122 complex_abs_ge(Complex * a, Complex * b)
123 {
124         double          amag = Mag(a),
125                                 bmag = Mag(b);
126
127         return amag >= bmag;
128 }
129
130 bool
131 complex_abs_gt(Complex * a, Complex * b)
132 {
133         double          amag = Mag(a),
134                                 bmag = Mag(b);
135
136         return amag > bmag;
137 }
138
139 int4
140 complex_abs_cmp(Complex * a, Complex * b)
141 {
142         double          amag = Mag(a),
143                                 bmag = Mag(b);
144
145         if (amag < bmag)
146                 return -1;
147         else if (amag > bmag)
148                 return 1;
149         else
150                 return 0;
151 }
152
153 /*****************************************************************************
154  * test code
155  *****************************************************************************/
156
157 /*
158  * You should always test your code separately. Trust me, using POSTGRES to
159  * debug your C function will be very painful and unproductive. In case of
160  * POSTGRES crashing, it is impossible to tell whether the bug is in your
161  * code or POSTGRES's.
162  */
163 void            test_main(void);
164 void
165 test_main()
166 {
167         Complex    *a;
168         Complex    *b;
169
170         a = complex_in("(4.01, 3.77 )");
171         printf("a = %s\n", complex_out(a));
172         b = complex_in("(1.0,2.0)");
173         printf("b = %s\n", complex_out(b));
174         printf("a +  b = %s\n", complex_out(complex_add(a, b)));
175         printf("a <  b = %d\n", complex_abs_lt(a, b));
176         printf("a <= b = %d\n", complex_abs_le(a, b));
177         printf("a =  b = %d\n", complex_abs_eq(a, b));
178         printf("a >= b = %d\n", complex_abs_ge(a, b));
179         printf("a >  b = %d\n", complex_abs_gt(a, b));
180 }