aboutsummaryrefslogtreecommitdiff
path: root/src/tutorial/C-code/complex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tutorial/C-code/complex.c')
-rw-r--r--src/tutorial/C-code/complex.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/tutorial/C-code/complex.c b/src/tutorial/C-code/complex.c
new file mode 100644
index 00000000000..bebdd511d4d
--- /dev/null
+++ b/src/tutorial/C-code/complex.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+/* do not include libpq-fe.h for backend-loaded functions*/
+/* #include "libpq-fe.h" */
+#include "postgres.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+
+typedef struct Complex {
+ double x;
+ double y;
+} Complex;
+
+/*****************************************************************************
+ * Input/Output functions
+ *****************************************************************************/
+
+Complex *
+complex_in(char *str)
+{
+ double x, y;
+ Complex *result;
+
+ if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) {
+ elog(WARN, "complex_in: error in parsing \"%s\"", str);
+ return NULL;
+ }
+ result = (Complex *)palloc(sizeof(Complex));
+ result->x = x;
+ result->y = y;
+ return (result);
+}
+
+/*
+ * You might have noticed a slight inconsistency between the following
+ * declaration and the SQL definition:
+ * CREATE FUNCTION complex_out(opaque) RETURNS opaque ...
+ * The reason is that the argument pass into complex_out is really just a
+ * pointer. POSTGRES thinks all output functions are:
+ * char *out_func(char *);
+ */
+char *
+complex_out(Complex *complex)
+{
+ char *result;
+
+ if (complex == NULL)
+ return(NULL);
+
+ result = (char *) palloc(60);
+ sprintf(result, "(%lg,%lg)", complex->x, complex->y);
+ return(result);
+}
+
+/*****************************************************************************
+ * New Operators
+ *****************************************************************************/
+
+Complex *
+complex_add(Complex *a, Complex *b)
+{
+ Complex *result;
+
+ result = (Complex *)palloc(sizeof(Complex));
+ result->x = a->x + b->x;
+ result->y = a->y + b->y;
+ return (result);
+}
+
+
+/*****************************************************************************
+ * Operator class for defining B-tree index
+ *****************************************************************************/
+
+#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
+
+bool
+complex_abs_lt(Complex *a, Complex *b)
+{
+ double amag = Mag(a), bmag = Mag(b);
+ return (amag<bmag);
+}
+
+bool
+complex_abs_le(Complex *a, Complex *b)
+{
+ double amag = Mag(a), bmag = Mag(b);
+ return (amag<=bmag);
+}
+
+bool
+complex_abs_eq(Complex *a, Complex *b)
+{
+ double amag = Mag(a), bmag = Mag(b);
+ return (amag==bmag);
+}
+
+bool
+complex_abs_ge(Complex *a, Complex *b)
+{
+ double amag = Mag(a), bmag = Mag(b);
+ return (amag>=bmag);
+}
+
+bool
+complex_abs_gt(Complex *a, Complex *b)
+{
+ double amag = Mag(a), bmag = Mag(b);
+ return (amag>bmag);
+}
+
+int4
+complex_abs_cmp(Complex *a, Complex *b)
+{
+ double amag = Mag(a), bmag = Mag(b);
+ if (a < b)
+ return -1;
+ else if (a > b)
+ return 1;
+ else
+ return 0;
+}
+
+/*****************************************************************************
+ * test code
+ *****************************************************************************/
+
+/*
+ * You should always test your code separately. Trust me, using POSTGRES to
+ * debug your C function will be very painful and unproductive. In case of
+ * POSTGRES crashing, it is impossible to tell whether the bug is in your
+ * code or POSTGRES's.
+ */
+void
+test_main()
+{
+ Complex *a;
+ Complex *b;
+
+ a = complex_in("(4.01, 3.77 )");
+ printf("a = %s\n", complex_out(a));
+ b = complex_in("(1.0,2.0)");
+ printf("b = %s\n", complex_out(b));
+ printf("a + b = %s\n", complex_out(complex_add(a,b)));
+ printf("a < b = %d\n", complex_abs_lt(a,b));
+ printf("a <= b = %d\n", complex_abs_le(a,b));
+ printf("a = b = %d\n", complex_abs_eq(a,b));
+ printf("a >= b = %d\n", complex_abs_ge(a,b));
+ printf("a > b = %d\n", complex_abs_gt(a,b));
+}