How do I create a user defined function in PostgreSQL that acts like the C function pair defined below?
Also, which type of function should I use and why?
(A) query language (SQL) function
(B) procedural language function
(C) internal function
(D) C-language function
(E) None of the above
Bonus points for implementations in both SQL & PL/pgSQL languages.
#include <stdio.h>
#include <math.h>
int pair(int x, int y)
{
int z;
if (x < y) {
z = x * (y-1);
y = y - x - 2;
} else {
z = (x-1) * y;
y = x - y - 2;
}
return z + pow(y, 2) / 4;
}
// TESTING
void test(int x, int y, int z)
{
printf("%s", pair(x, y) == z ? "." : "F");
}
int main(void)
{
test(1, 2, 1);
test(1, 3, 2);
test(1, 4, 3);
test(1, 5, 5);
test(1, 6, 7);
test(1, 7, 10);
test(1, 8, 13);
test(1, 9, 17);
test(2, 3, 4);
test(2, 4, 6);
test(2, 5, 8);
test(2, 6, 11);
test(2, 7, 14);
test(2, 8, 18);
test(2, 9, 22);
printf("\n");
return 0;
}
Use an SQL CASE statement:
CASE WHEN x < y THEN
x * (y - 1) + ((y - x - 2)^2)::int / 4
ELSE
(x - 1) * y + ((x - y - 2)^2)::int / 4
END
The operator ^ as well as the function power() return double precision. So I cast to int to match your question.
Wrapped into a plain SQL function (with operator ^):
CREATE OR REPLACE FUNCTION pair1(x int, y int)
RETURNS int AS
$func$
SELECT CASE WHEN x < y THEN
x * (y - 1) + ((y - x - 2)^2)::int / 4
ELSE
(x - 1) * y + ((x - y - 2)^2)::int / 4
END
$func$ LANGUAGE sql IMMUTABLE;
In Postgres 9.1 or older you have tro reference input columns with positional parameters $1, $2 instead.
The same as PL/pgSQL function (with function power()):
CREATE OR REPLACE FUNCTION pair2(x int, y int)
RETURNS int AS
$func$
BEGIN
RETURN CASE WHEN x < y THEN
x * (y - 1) + power(y - x - 2, 2)::int / 4
ELSE
(x - 1) * y + power(x - y - 2, 2)::int / 4
END;
END
$func$ LANGUAGE plpgsql IMMUTABLE;
SQL Fiddle demo.
I depends, but generally I would use a simple SQL function. And don't forget to declare it IMMUTABLE. This allows various performance optimizations in bigger queries and using it in functional indexes. Example with more details:
Does PostgreSQL support "accent insensitive" collations?
SQL is simpler. If x < y it will return the first element of the array else the second
create or replace function pair(x int, y int)
returns double precision as $$
select (array[
x * (y - 1) + power(y - x - 2, 2) / 4,
(x - 1) * y + power(x - y - 2, 2) / 4
])[(not x < y)::int + 1]
;
$$ language sql;
select
pair(1, 2) = 1,
pair(1, 3) = 2,
pair(1, 4) = 3,
pair(1, 5) = 5,
pair(1, 6) = 7,
pair(1, 7) = 10,
pair(1, 8) = 13,
pair(1, 9) = 17,
pair(2, 3) = 4,
pair(2, 4) = 6,
pair(2, 5) = 8,
pair(2, 6) = 11,
pair(2, 7) = 14,
pair(2, 8) = 18,
pair(2, 9) = 22
;
A boolean casted to integer yields 1 or 0. As Postgresql array index starts at 1 then 1 is added to the result of the casting.
Related
I am reading Scala for the Impatient, Chapter 2 and there is an exercise question I don't understanding what exactly does it want:
Write a function that computes x^n, where n is an integer. Use the
following recursive definition:
X^n = y * y if n is even and positive, where y = x^(n/2)
X^n = x * x^(n-1) if n is odd and positive
x^0 = 1
x^n = 1 / x^-n if n is negative
If the question want x^n, I could just use the pow method defined in scala.math:
def pow(x: Double, y: Double): Double
The question is asking to (re)implement a recursive pow function on integers:
def pow(x: Int, y: Int): Int = ...
You need write a smarter implementation than the naive O(n) algorithm:
def slowPow(x: Int, y: Int): Int =
if (y == 0) 1 else x * slowPow(x, y - 1)
Try to use the given recursive definition instead...
To answer your question directly, I don't think you can dodge the question using the one from scala.math. As you noted it only works on Doubles. Also is neither recursive nor implemented in Scala.
def pow(x: Double, n: Int): Double = {
if (n == 0) 1
else if (n < 0) 1 / (x - n)
else if (n % 2 == 1) x * pow(x, n - 1)
else {
val y = pow(x, n / 2)
y * y
}
}
pow(2, 0) == 1
pow(2, -2) == 0.25
pow(2, 4) == 16
pow(2, 5) == 32
How can I do below calculations (finding C) without using "for loop"?
[4, 2, 1, 7;
A = 0, 3, 4, 0;
8, 0, 10, 12;
11, 6, 2, 5];
[1, 0, 0, 4;
B = 0, 3, 2, 0;
5, 0, 8, 10;
7, 2, 1, 2];
C(i,j)= B(i,j-1) - B(i,j+1) + A(i,j+1); %if j is not equal to 4(number of columns) and it is not equal to 1
C(i,j)= B(i,4) - B(i,j+1) + A(i,j+1); %if j is equal to 1
C(i,j)= B(i,j-1) - B(i,1) + A(i,1); %if j is equal to 4(number of columns)
You can specify an array as index to work on multiple element at the same time:
A=[4,2,1,7;0,3,4,0;8,0,10,12;11,6,2,5];
B=[1,0,0,4;0,3,2,0;5,0,8,10;7,2,1,2];
C = zeros(size(A));
C(:,2:end-1) = B(:,1:end-2) - B(:,3:end) + A(:,3:end); %if j is not equal to 4(number of columns) and it is not equal to 1
j = 1;
C(:,j)= B(:,4) - B(:,j+1) + A(:,j+1); %if j is equal to 1
j = 4;
C(:,j)= B(:,j-1) - B(:,1) + A(:,1); %if j is equal to 4(number of columns)
I'm trying to implement the active contour models algorithm with c++ and opencv in VisualStudio.
I'm having trouble creating a pentadiagonal matrix, that is a matrix with the five main diagonals with values and zeros in the rest of the matrix.
I've already implemented this in MatLab, that came out like this:
K = diag(repmat(a,1,n));
K = K + diag(repmat(b,1,n-1),1) + diag(repmat(b,1,n-1),-1)...
+ diag(b,n-1) + diag(b,-n+1);
K = K + diag(repmat(c,1,n-2),2) + diag(repmat(c,1,n-2),-2)...
+ diag([c c],n-2) + diag([c c],-n+2);
How do I do the same thing in opencv?
Thanks!
You can wrap the Matlab functions repmat and diag as in the code below.
Then you can write the OpenCV code as in Matlab. The only difference is that you cannot concatenate 2 matrices with [c c], but you should use repmat(c, 2, 1), or repmat(c,1,2) for [c; c].
Code:
#include <opencv2\opencv.hpp>
using namespace cv;
Mat repmat(const Mat& src, int nx, int ny)
{
return repeat(src, nx, ny);
}
Mat diag(const Mat& src, int k=0)
{
// src must be a row or column matrix
//CV_Assert(src.rows == 1 || src.cols == 2);
int n = src.rows * src.cols;
Mat1d _src;
src.convertTo(_src, CV_64F);
// Create output matrix of correct dimension
int dim = n + abs(k);
Mat1d _dst(dim, dim, double(0.0));
// Select the ranges where to put src data
Range rrows;
Range rcols;
if (k >= 0)
{
rrows = Range(0, n);
rcols = Range(k, k+n);
}
else
{
rrows = Range(-k, -k + n);
rcols = Range(0, n);
}
// Create square n x n submatrix
Mat1d sub(_dst(rrows, rcols));
// Put data on the diagonal of the submatrix
for (int i = 0; i < n; ++i)
{
sub(i, i) = _src(i);
}
Mat dst;
_dst.convertTo(dst, src.type());
return dst;
}
int main()
{
Mat a;
Mat b;
Mat c;
int n;
// ... init a, b, c, n
Mat K;
K = diag(repmat(a, 1, n));
K = K + diag(repmat(b, 1, n - 1), 1) + diag(repmat(b, 1, n - 1), -1) + diag(b, n - 1) + diag(b, -n + 1);
K = K + diag(repmat(c, 1, n - 2), 2) + diag(repmat(c, 1, n - 2), -2) + diag(repmat(b, 2, 1), n - 2) + diag(repmat(b, 2, 1), -n + 2);
return 0;
}
I tried the following:
spline= interpolate.InterpolatedUnivariateSpline(X, Y, k=3)
coefs= spline.get_coeffs()
With five values in each of X and Y, I ended up with coefs also having
five values. Given that five data points implies four spline sections, and
that a cubic polynomial has four coefficients, I would have expected to get
four times four= 16 coefficients. Does anyone know how to interpret the values that are returned by the get_coeffs method? Is there any place where this is documented?
These are not the coefficients of x, x**2, and so forth: such monomials are ill-suited to representing splines. Rather, they are coefficients of B-splines which are computed for the specific grid on which interpolation is done. The number of B-splines involved is equal to the number of data points, and so is the number of coefficients. As an example, suppose we want to interpolate these data:
xv = [0, 1, 2, 3, 4, 5]
yv = [3, 6, 5, 7, 9, 1]
Begin with the simpler case of degree k=1 (piecewise linear spline). Then the B-splines are these "triangular hat" functions:
There are 6 of them. Each of them is equal to 1 at "its" grid point, and 0 at all other grid points. This makes it really easy to write the interpolating spline: it is y[0]*b[0] + ... + y[5]*b[5]. And indeed, get_coeffs shows the coefficients are the the y-values themselves.
InterpolatedUnivariateSpline(xv, yv, k=1).get_coeffs() # [ 3., 6., 5., 7., 9., 1.]
Cubic splines
Now it gets hairy, because we need "hats" that are smooth, rather than pointy as those above. The smoothness requirement forces them to be wider, so each B-spline has nonzero values on several grid points. (Technicality: a cubic B-spline has nonzero values at up to 3 knots, but on the chart below, 1 and 4, despite being grid points, are not knots due to so-called "not a knot" condition. Never mind this.) Here are the B-splines for our grid:
To get these, I used older methods splrep and splev of scipy.interpolate, which call the same fitpack routines under the hood. The coefficient vector here is the second entry of the tuple tck; I modify it to have one 1 and the rest 0, thus creating a basis spline (b-spline).
k = 3
tck = splrep(xv, yv, s=0, k=k)
xx = np.linspace(min(xv), max(xv), 500)
bsplines = []
for j in range(len(xv)):
tck_mod = (tck[0], np.arange(len(xv)+2*k-2) == j, k)
bsplines.append(splev(xx, tck_mod))
plt.plot(xx, bsplines[-1])
Now that we have a list bsplines, we can use the coefficients returned by get_coeffs to put them together ourselves into an interpolating spline:
coeffs = InterpolatedUnivariateSpline(xv, yv, k=3).get_coeffs()
interp_spline = sum([coeff*bspline for coeff, bspline in zip(coeffs, bsplines)])
plt.plot(xx, interp_spline)
If you want a formula for the pieces of these B-splines, the Cox-de Boor recursion formula on B-splines can help but these are a chore to compute by hand.
SymPy can give formulas for B-splines, but there is a little twist. One should pass in a padded set of knots, by repeating the end values like
[0, 0, 0, 0, 2, 3, 5, 5, 5, 5]
This is because at 0 and 5 all four coefficients change values, while at 1 and 4 none of them do, so they are omitted ("not a knot"). (Also, the current version of SymPy (1.1.1) has an issue with repeated knots, but this will be fixed in the next version.)
from sympy import symbols, bspline_basis_set, plot
x = symbols('x')
xv_padded = [0, 0, 0, 0, 2, 3, 5, 5, 5, 5]
bs = bspline_basis_set(3, xv_padded, x)
Now bs is an array of scary-looking piecewise formulas:
[Piecewise((-x**3/8 + 3*x**2/4 - 3*x/2 + 1, (x >= 0) & (x <= 2)), (0, True)),
Piecewise((19*x**3/72 - 5*x**2/4 + 3*x/2, (x >= 0) & (x <= 2)), (-x**3/9 + x**2 - 3*x + 3, (x >= 2) & (x <= 3)), (0, True)),
Piecewise((-31*x**3/180 + x**2/2, (x >= 0) & (x <= 2)), (11*x**3/45 - 2*x**2 + 5*x - 10/3, (x >= 2) & (x <= 3)), (-x**3/30 + x**2/2 - 5*x/2 + 25/6, (x >= 3) & (x <= 5)), (0, True)),
Piecewise((x**3/30, (x >= 0) & (x <= 2)), (-11*x**3/45 + 5*x**2/3 - 10*x/3 + 20/9, (x >= 2) & (x <= 3)), (31*x**3/180 - 25*x**2/12 + 95*x/12 - 325/36, (x >= 3) & (x <= 5)), (0, True)),
Piecewise((x**3/9 - 2*x**2/3 + 4*x/3 - 8/9, (x >= 2) & (x <= 3)), (-19*x**3/72 + 65*x**2/24 - 211*x/24 + 665/72, (x >= 3) & (x <= 5)), (0, True)),
Piecewise((x**3/8 - 9*x**2/8 + 27*x/8 - 27/8, (x >= 3) & (x <= 5)), (0, True))]
I have the following:
#define PAD ( 4 - ( (WIDTH*BPP)%4 ) )
#if PAD == 4
#define PAD 0
#endif
and PAD is redefined even though it is equal to 3 after the first definition. However if I explicitly define it as 3 then it isn't redefined. Therefore I assume there is a problem with the way I have written the expression, but I'm not sure what.
What you want is
(PAD + (WIDTH * BPP)) % 4 == 0
right? (Of course 0 <= PAD < 4)
Then you can define PAD in this way:
#define PAD (3 - ((WIDTH * BPP + 3) % 4))
Example Python session:
>>> def f(x): return 3 - (x+3)%4
...
>>> [ (x, f(x), x + f(x)) for x in xrange(100,108) ]
[(100, 0, 100), (101, 3, 104), (102, 2, 104), (103, 1, 104), (104, 0, 104), (105, 3, 108), (106, 2, 108), (107, 1, 108)]
In general,
#define PAD ((N-1) - (X + (N-1)) % N))
makes PAD + X a multiple of N under a constraint of 0 <= PAD < N (Though I didn't check negative cases...)