cpc error bounds
diff --git a/sql/datasketches_cpc_sketch.sql b/sql/datasketches_cpc_sketch.sql
index b86453a..4c293e3 100644
--- a/sql/datasketches_cpc_sketch.sql
+++ b/sql/datasketches_cpc_sketch.sql
@@ -46,6 +46,14 @@
     AS '$libdir/datasketches', 'pg_cpc_sketch_get_estimate'
     LANGUAGE C STRICT IMMUTABLE;
 
+CREATE OR REPLACE FUNCTION cpc_sketch_get_estimate_and_bounds(cpc_sketch) RETURNS double precision[]
+    AS '$libdir/datasketches', 'pg_cpc_sketch_get_estimate_and_bounds'
+    LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION cpc_sketch_get_estimate_and_bounds(cpc_sketch, int) RETURNS double precision[]
+    AS '$libdir/datasketches', 'pg_cpc_sketch_get_estimate_and_bounds'
+    LANGUAGE C STRICT IMMUTABLE;
+
 CREATE OR REPLACE FUNCTION cpc_sketch_from_internal(internal) RETURNS cpc_sketch
     AS '$libdir/datasketches', 'pg_cpc_sketch_from_internal'
     LANGUAGE C STRICT IMMUTABLE;
diff --git a/src/cpc_sketch_c_adapter.cpp b/src/cpc_sketch_c_adapter.cpp
index 30c7f24..6900380 100644
--- a/src/cpc_sketch_c_adapter.cpp
+++ b/src/cpc_sketch_c_adapter.cpp
@@ -19,10 +19,6 @@
 
 #include "cpc_sketch_c_adapter.h"
 
-extern "C" {
-#include <postgres.h>
-}
-
 #include <sstream>
 
 #include <cpc_sketch.hpp>
@@ -62,6 +58,18 @@
   }
 }
 
+Datum* cpc_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs) {
+  try {
+    Datum* est_and_bounds = (Datum*) palloc(sizeof(Datum) * 3);
+    est_and_bounds[0] = Float8GetDatum(static_cast<const datasketches::cpc_sketch*>(sketchptr)->get_estimate());
+    est_and_bounds[1] = Float8GetDatum(static_cast<const datasketches::cpc_sketch*>(sketchptr)->get_lower_bound(num_std_devs));
+    est_and_bounds[2] = Float8GetDatum(static_cast<const datasketches::cpc_sketch*>(sketchptr)->get_upper_bound(num_std_devs));
+    return est_and_bounds;
+  } catch (std::exception& e) {
+    elog(ERROR, e.what());
+  }
+}
+
 void cpc_sketch_to_string(const void* sketchptr, char* buffer, unsigned length) {
   try {
     std::stringstream s;
diff --git a/src/cpc_sketch_c_adapter.h b/src/cpc_sketch_c_adapter.h
index 47ab68c..962040e 100644
--- a/src/cpc_sketch_c_adapter.h
+++ b/src/cpc_sketch_c_adapter.h
@@ -24,12 +24,15 @@
 extern "C" {
 #endif
 
+#include <postgres.h>
+
 void* cpc_sketch_new(unsigned lg_k);
 void cpc_sketch_delete(void* sketchptr);
 
 void cpc_sketch_update(void* sketchptr, const void* data, unsigned length);
 void cpc_sketch_merge(void* sketchptr1, const void* sketchptr2);
 double cpc_sketch_get_estimate(const void* sketchptr);
+Datum* cpc_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs);
 void cpc_sketch_to_string(const void* sketchptr, char* buffer, unsigned length);
 
 void* cpc_sketch_serialize(const void* sketchptr);
diff --git a/src/cpc_sketch_pg_functions.c b/src/cpc_sketch_pg_functions.c
index f37cde8..6edc5d3 100644
--- a/src/cpc_sketch_pg_functions.c
+++ b/src/cpc_sketch_pg_functions.c
@@ -21,6 +21,8 @@
 #include <fmgr.h>
 #include <utils/lsyscache.h>
 #include <utils/builtins.h>
+#include <utils/array.h>
+#include <catalog/pg_type.h>
 
 #include "cpc_sketch_c_adapter.h"
 #include "base64.h"
@@ -30,6 +32,7 @@
 /* PG_FUNCTION_INFO_V1 macro to pass functions to postgres */
 PG_FUNCTION_INFO_V1(pg_cpc_sketch_add_item);
 PG_FUNCTION_INFO_V1(pg_cpc_sketch_get_estimate);
+PG_FUNCTION_INFO_V1(pg_cpc_sketch_get_estimate_and_bounds);
 PG_FUNCTION_INFO_V1(pg_cpc_sketch_to_string);
 PG_FUNCTION_INFO_V1(pg_cpc_sketch_union_agg);
 PG_FUNCTION_INFO_V1(pg_cpc_sketch_from_internal);
@@ -42,6 +45,7 @@
 Datum pg_cpc_sketch_send(PG_FUNCTION_ARGS);
 Datum pg_cpc_sketch_add_item(PG_FUNCTION_ARGS);
 Datum pg_cpc_sketch_get_estimate(PG_FUNCTION_ARGS);
+Datum pg_cpc_sketch_get_estimate_and_bounds(PG_FUNCTION_ARGS);
 Datum pg_cpc_sketch_to_string(PG_FUNCTION_ARGS);
 Datum pg_cpc_sketch_union_agg(PG_FUNCTION_ARGS);
 Datum pg_cpc_sketch_from_internal(PG_FUNCTION_ARGS);
@@ -111,6 +115,31 @@
   PG_RETURN_FLOAT8(estimate);
 }
 
+Datum pg_cpc_sketch_get_estimate_and_bounds(PG_FUNCTION_ARGS) {
+  const bytea* bytes_in;
+  void* sketchptr;
+  int num_std_devs;
+
+  // output array
+  Datum* est_and_bounds;
+  ArrayType* arr_out;
+  int16 elmlen_out;
+  bool elmbyval_out;
+  char elmalign_out;
+
+  bytes_in = PG_GETARG_BYTEA_P(0);
+  sketchptr = cpc_sketch_deserialize(VARDATA(bytes_in), VARSIZE(bytes_in) - VARHDRSZ);
+  num_std_devs = PG_GETARG_INT32(1);
+  if (num_std_devs == 0) num_std_devs = 1; // default
+  est_and_bounds = cpc_sketch_get_estimate_and_bounds(sketchptr, num_std_devs);
+  cpc_sketch_delete(sketchptr);
+
+  // construct output array
+  get_typlenbyvalalign(FLOAT8OID, &elmlen_out, &elmbyval_out, &elmalign_out);
+  arr_out = construct_array(est_and_bounds, 3, FLOAT8OID, elmlen_out, elmbyval_out, elmalign_out);
+  PG_RETURN_ARRAYTYPE_P(arr_out);
+}
+
 Datum pg_cpc_sketch_to_string(PG_FUNCTION_ARGS) {
   const bytea* bytes_in;
   void* sketchptr;