pgbench_pow_v10_ipow_overflow.patch
text/x-patch
Filename: pgbench_pow_v10_ipow_overflow.patch
Type: text/x-patch
Part: 1
Patch
Format: format-patch
Series: patch v10
Subject: Add pow() support to pgbench
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/pgbench.sgml | 7 | 0 |
| src/bin/pgbench/exprparse.y | 6 | 0 |
| src/bin/pgbench/pgbench.c | 100 | 0 |
| src/bin/pgbench/pgbench.h | 2 | 1 |
| src/bin/pgbench/t/001_pgbench_with_server.pl | 21 | 1 |
From 6cb8fb1a3eaffe680b85913b0acf0068dcb0d2a7 Mon Sep 17 00:00:00 2001
From: Raul Marin <rmrodriguez@cartodb.com>
Date: Thu, 21 Dec 2017 20:28:02 +0100
Subject: [PATCH] Add pow() support to pgbench
---
doc/src/sgml/ref/pgbench.sgml | 7 ++
src/bin/pgbench/exprparse.y | 6 ++
src/bin/pgbench/pgbench.c | 100 +++++++++++++++++++++++++++
src/bin/pgbench/pgbench.h | 3 +-
src/bin/pgbench/t/001_pgbench_with_server.pl | 22 +++++-
5 files changed, 136 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 4431fc3eb7..1519fe78ef 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -1069,6 +1069,13 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
<entry><literal>pi()</literal></entry>
<entry><literal>3.14159265358979323846</literal></entry>
</row>
+ <row>
+ <entry><literal><function>pow(<replaceable>x</replaceable>, <replaceable>y</replaceable>)</function>, <function>power(<replaceable>x</replaceable>, <replaceable>y</replaceable>)</function></literal></entry>
+ <entry>double</entry>
+ <entry>exponentiation</entry>
+ <entry><literal>pow(2.0, 10)</literal>, <literal>power(2.0, 10)</literal></entry>
+ <entry><literal>1024.0</literal></entry>
+ </row>
<row>
<entry><literal><function>random(<replaceable>lb</replaceable>, <replaceable>ub</replaceable>)</function></literal></entry>
<entry>integer</entry>
diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y
index 25d5ad48e5..74ffe5e7a7 100644
--- a/src/bin/pgbench/exprparse.y
+++ b/src/bin/pgbench/exprparse.y
@@ -194,6 +194,12 @@ static const struct
{
"random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN
},
+ {
+ "pow", 2, PGBENCH_POW
+ },
+ {
+ "power", 2, PGBENCH_POW
+ },
/* keep as last array element */
{
NULL, 0, 0
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 7ce6f607f5..07436af5a7 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -911,6 +911,64 @@ getZipfianRand(TState *thread, int64 min, int64 max, double s)
: computeHarmonicZipfian(thread, n, s));
}
+/* Position of the most significant bit */
+static int64
+ffs_i64(int64 i)
+{
+ int64 bits = 0;
+
+ if (i < 0)
+ i = -i;
+ while (i)
+ {
+ i>>=1;
+ bits++;
+ }
+
+ return bits;
+}
+
+/* Heuristic to check for ipow overflow */
+static bool
+ipow_check_overflow(int64 base, int64 exp)
+{
+ int64 msb_base,
+ msb_base_sqr;
+
+ Assert(exp >= 0);
+ if (base == 0 || base == 1 || base == -1 || exp <= 1)
+ return false;
+
+ msb_base = ffs_i64(base);
+ if (msb_base >= 32)
+ return true;
+
+ msb_base_sqr = ffs_i64(base * base);
+ if (msb_base_sqr <= msb_base)
+ return true;
+
+ return (msb_base + (msb_base_sqr - msb_base) * (exp -1)) > 63;
+}
+
+/* Faster power function for integer values with exp >= 0 */
+static int64
+ipow(int64 base, int64 exp)
+{
+ int64 result = 1;
+
+ Assert(exp >= 0);
+
+ while (exp)
+ {
+ if (exp & 1)
+ result *= base;
+ exp >>= 1;
+ base *= base;
+ }
+
+ return result;
+}
+
/*
* Initialize the given SimpleStats struct to all zeroes
*/
@@ -1850,6 +1908,48 @@ evalFunc(TState *thread, CState *st,
return true;
}
+ case PGBENCH_POW:
+ {
+ PgBenchValue *lval = &vargs[0];
+ PgBenchValue *rval = &vargs[1];
+
+ Assert(nargs == 2);
+
+ /*
+ * If both operands are int, exp >= 0 and the output
+ * fits in an int64 use the faster ipow(), else use pow()
+ */
+ if (lval->type == PGBT_INT &&
+ rval->type == PGBT_INT)
+ {
+
+ int64 li,
+ ri;
+
+ if (!coerceToInt(lval, &li) ||
+ !coerceToInt(rval, &ri))
+ return false;
+
+ if (ri >= 0 &&
+ !ipow_check_overflow(li,ri))
+ setDoubleValue(retval, ipow(li, ri));
+ else
+ setDoubleValue(retval, pow(li, ri));
+ }
+ else
+ {
+ double ld,
+ rd;
+
+ if (!coerceToDouble(lval, &ld) ||
+ !coerceToDouble(rval, &rd))
+ return false;
+
+ setDoubleValue(retval, pow(ld, rd));
+ }
+ return true;
+ }
+
default:
/* cannot get here */
Assert(0);
diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h
index 83fee1ae74..0e92882a4c 100644
--- a/src/bin/pgbench/pgbench.h
+++ b/src/bin/pgbench/pgbench.h
@@ -76,7 +76,8 @@ typedef enum PgBenchFunction
PGBENCH_RANDOM,
PGBENCH_RANDOM_GAUSSIAN,
PGBENCH_RANDOM_EXPONENTIAL,
- PGBENCH_RANDOM_ZIPFIAN
+ PGBENCH_RANDOM_ZIPFIAN,
+ PGBENCH_POW
} PgBenchFunction;
typedef struct PgBenchExpr PgBenchExpr;
diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl
index e3cdf28628..9cbeb2fc11 100644
--- a/src/bin/pgbench/t/001_pgbench_with_server.pl
+++ b/src/bin/pgbench/t/001_pgbench_with_server.pl
@@ -232,7 +232,17 @@ pgbench(
qr{command=19.: double 19\b},
qr{command=20.: double 20\b},
qr{command=21.: int 9223372036854775807\b},
- qr{command=23.: int [1-9]\b}, ],
+ qr{command=23.: int [1-9]\b},
+ qr{command=24.: double -27\b},
+ qr{command=25.: double 1024\b},
+ qr{command=26.: double 1\b},
+ qr{command=27.: double 1\b},
+ qr{command=28.: double -0.125\b},
+ qr{command=29.: double -0.125\b},
+ qr{command=30.: double -0.00032\b},
+ qr{command=31.: double 8.50705917302346e\+37\b},
+ qr{command=32.: double 1e\+30\b},
+ ],
'pgbench expressions',
{ '001_pgbench_expressions' => q{-- integer functions
\set i1 debug(random(1, 100))
@@ -264,6 +274,16 @@ pgbench(
\set i1 0
-- yet another integer function
\set id debug(random_zipfian(1, 9, 1.3))
+--- pow and power
+\set poweri debug(pow(-3,3))
+\set powerd debug(pow(2.0,10))
+\set poweriz debug(pow(0,0))
+\set powerdz debug(pow(0.0,0.0))
+\set powernegi debug(pow(-2,-3))
+\set powernegd debug(pow(-2.0,-3.0))
+\set powernegd2 debug(power(-5.0,-5.0))
+\set powerov debug(pow(9223372036854775807, 2))
+\set powerov2 debug(pow(10,30))
} });
# backslash commands
--
2.15.1