Inverse of Cumulative Normal Distribution Function with parameters - c++

I want to implement equivalent of matlab icdf function in C++, I have already found this useful post: https://www.johndcook.com/blog/cpp_phi_inverse/. But I want it with optional mu and sigma parameters as in matlab.
What I am supposed to change?

Inspired from https://gist.github.com/kmpm/1211922/6b7fcd0155b23c3dc71e6f4969f2c48785371292:
double inverse_of_normal_cdf(const double p, const double mu, const double sigma)
{
if (p <= 0.0 || p >= 1.0)
{
std::stringstream os;
os << "Invalid input argument (" << p
<< "); must be larger than 0 but less than 1.";
throw std::invalid_argument(os.str());
}
double r, val;
const double q = p - 0.5;
if (std::abs(q) <= .425) {
r = .180625 - q * q;
val =
q * (((((((r * 2509.0809287301226727 +
33430.575583588128105) * r + 67265.770927008700853) * r +
45921.953931549871457) * r + 13731.693765509461125) * r +
1971.5909503065514427) * r + 133.14166789178437745) * r +
3.387132872796366608)
/ (((((((r * 5226.495278852854561 +
28729.085735721942674) * r + 39307.89580009271061) * r +
21213.794301586595867) * r + 5394.1960214247511077) * r +
687.1870074920579083) * r + 42.313330701600911252) * r + 1);
}
else {
if (q > 0) {
r = 1 - p;
}
else {
r = p;
}
r = std::sqrt(-std::log(r));
if (r <= 5)
{
r += -1.6;
val = (((((((r * 7.7454501427834140764e-4 +
.0227238449892691845833) * r + .24178072517745061177) *
r + 1.27045825245236838258) * r +
3.64784832476320460504) * r + 5.7694972214606914055) *
r + 4.6303378461565452959) * r +
1.42343711074968357734)
/ (((((((r *
1.05075007164441684324e-9 + 5.475938084995344946e-4) *
r + .0151986665636164571966) * r +
.14810397642748007459) * r + .68976733498510000455) *
r + 1.6763848301838038494) * r +
2.05319162663775882187) * r + 1);
}
else { /* very close to 0 or 1 */
r += -5;
val = (((((((r * 2.01033439929228813265e-7 +
2.71155556874348757815e-5) * r +
.0012426609473880784386) * r + .026532189526576123093) *
r + .29656057182850489123) * r +
1.7848265399172913358) * r + 5.4637849111641143699) *
r + 6.6579046435011037772)
/ (((((((r *
2.04426310338993978564e-15 + 1.4215117583164458887e-7) *
r + 1.8463183175100546818e-5) * r +
7.868691311456132591e-4) * r + .0148753612908506148525)
* r + .13692988092273580531) * r +
.59983220655588793769) * r + 1);
}
if (q < 0.0) {
val = -val;
}
}
return mu + sigma * val;
}

Related

How can I "join" quadratic or cubic splines?

I have 2 function to either calculate a point on a spline, quadratic or cubic:
struct vec2 {float x, y;};
vec2 spline_quadratic(vec2 & a, vec2 & b, vec2 & c, float t) {
return {
(1 - t) * (1 - t) * p1.x + 2 * (1 - t) * t * p2.x + t * t * p3.x,
(1 - t) * (1 - t) * p1.y + 2 * (1 - t) * t * p2.y + t * t * p3.y
};
}
vec2 spline_cubic(vec2 & a, vec2 & b, vec2 & c, vec2 & d, float t){
return {
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
(1 - t) * (1 - t) * (1 - t) * p1.x + 3 * (1 - t) * (1 - t) * t * p2.x + 3 * (1 - t) * t * t * p3.x + t * t * t * p4.x,
(1 - t) * (1 - t) * (1 - t) * p1.y + 3 * (1 - t) * (1 - t) * t * p2.y + 3 * (1 - t) * t * t * p3.y + t * t * t * p4.y
};
Is it possible to join several curves of an array of points?
I'm looking to make a function that has this signature:
vector<vec2> spline_join(vector<vec2> & points, int segments = 16){
vector<vec2> spline_points;
for(int i = 0; i < points.size()-2; ++i){
for(int div = 0; div < segments; ++div){
spline_points.push_back(spline_quadratic(points[0], points[1], points[2], 1.f/segments);
}
}
}
I've read that it requires interpolation, but I'm not sure... What would the code look like? I've searched and I can't find relevant question and answers...
I've seen there are libraries, but I'm looking for a shorter implementation.
Edit: I've tried the question and answer here and apparently this is what I want:
Joining B-Spline segments in OpenGL / C++
The code is not really clean but after some cleaning, it does work.
I've cleaned this answer Joining B-Spline segments in OpenGL / C++
This is not an Hermite spline, an hermite spline passes through the points, a B-spline does not.
Here is what worked and the result
float B0(float u) {
//return float(pow(u - 1, 3) / 6.0);
// (1-t)*(1-t)*(1-t)/6.f
return float(pow(1-u, 3) / 6.0);
}
float B1(float u) {
return float((3 * pow(u, 3) - 6 * pow(u, 2) + 4) / 6.0);
// (3 * t * t * t - 6 * t * t + 4) / 6
}
float B2(float u) {
return float((-3 * pow(u, 3) + 3 * pow(u, 2) + 3 * u + 1) / 6.0);
// (-3 * t * t * t + 3 * t * t + 3 * t + 1) / 6
}
float B3(float u) {
return float(pow(u, 3) / 6.0);
// t * t * t / 6
}
vector<Vec2> computeBSpline(vector<Vec2>& points) {
vector<Vec2> result;
int MAX_STEPS = 100;
int NUM_OF_POINTS = points.size();
for (int i = 0; i < NUM_OF_POINTS - 3; i++)
{
//cout << "Computing for P" << i << " P " << i + 1 << " P " << i + 2 << " P " << i + 3 << endl;
for (int j = 0; j <= MAX_STEPS; j++)
{
float u = float(j) / float(MAX_STEPS);
float Qx =
B0(u) * points[i].x
+ B1(u) * points[i + 1].x
+ B2(u) * points[i + 2].x
+ B3(u) * points[i + 3].x;
float Qy =
B0(u) * points[i].y
+ B1(u) * points[i + 1].y
+ B2(u) * points[i + 2].y
+ B3(u) * points[i + 3].y;
result.push_back({ Qx, Qy });
//cout << count << '(' << Qx << ", " << Qy << ")\n";
}
}
return result;
}

Converting RGB to Luv

i'm trying to convert an rgb image to Luv, i have some problem. The L component is good, but when i show the u and v component both are black(all pixels have value 0).
for (int i = 0; i<height; i++)
for (int j = 0; j<width; j++)
{
Vec3b v3 = src.at<Vec3b>(i, j);
float b = ((float)v3[0]) / 255;
float g = ((float)v3[1]) / 255;
float r = ((float)v3[2]) / 255;
float x = r * 0.412453 + g * 0.357580 + b * 0.180423;
float y = r * 0.212671 + g * 0.715160 + b * 0.072169;
float z = r * 0.019334 + g * 0.119193 + b * 0.950227;
//L
if (y > 0.008856) {
l_mat.at<uchar>(i, j) = 255 / 100 * (116 * pow(y, 1.0 / 3.0));
dst.at<Vec3b>(i, j)[0] = 255 / 100 * (116 * pow(y, 1.0 / 3.0));
// printf("%d / " , l_mat.at<uchar>(i, j));
}
else {
l_mat.at<uchar>(i, j) = 255 / 100 * (903.3 * y);
dst.at<Vec3b>(i, j)[0] = 255 / 100 * (903.3 * y);
}
float u = 4 * x / (x + 15 * y + 3 * z);
float v = 9 * y / (x + 15 * y + 3 * z);
//printf("u: %.2f , v:%.2f || ", u, v);
//U
u_mat.at<uchar>(i, j) = 255 / 354 * (13 * l_mat.at<uchar>(i, j)*(u - 0.19793943) + 134);
//printf("%d / ", u_mat.at<uchar>(i, j));
dst.at<Vec3b>(i, j) = 255 / 354 * (13 * l_mat.at<uchar>(i, j)*(u - 0.19793943) + 134);
//v
v_mat.at<uchar>(i, j) = 255 / 262 * (13 * l_mat.at<uchar>(i, j)*(v - 0.46831096)+140);
dst.at<Vec3b>(i, j) = 255 / 262 * (13 * l_mat.at<uchar>(i, j)*(v - 0.46831096) + 140);
}
I have to do the conversions pixel by pixel, i can't use cvtcolor.

C++ for loop stops before reaching end and restarts

I've been poking my nose into working with arrays in c++ and I've been writing a 1D Euler solver code that I wrote in matlab and converting it to c++ as a practice exercise.
This issue is that this for loop is supposed to run until the counter i reaches N_cells-1 but no matter how high I set the number, it always gets to 57, then restarts from 2 and continues doing this until I click on the output screen. I also ran the code with an N_cells number less than 57 and I get an error code which I've included below.
I'm pretty new to arrays and header files in c++ so I'm sure it's something simple, but I just can't find it. I know it's related to the fqL array but I don't know what.
Error when number <57 is used:
#include "stdafx.h"
#include "Flux.h"
#include <iostream>
#include <chrono>
using namespace std;
void Flux(double * q, double y, double R, int N_cells,double * Flux)
{
double qL[3];
double qR[3];
for (int i = 0; i < N_cells - 1; i++) {
//Initialize left and right sides
//-------------------
qL[0] = q[0, i];
qL[1] = q[1, i];
qL[2] = q[2, i];
qR[0] = q[0, i + 1];
qR[1] = q[1, i + 1];
qR[2] = q[2, i + 1];
//-------------------
//Calculate Left side Parameters
//-------------------
double PL;
//double fqL[3];
double cL2;
double HL;
double uL;
PL = (y - 1)*(qL[2] - 0.5 / qL[0] * (qL[1] * qL[1]));
double fqL[3] = { qL[1],
(3 - y)*0.5*(qL[1] * qL[1]) / qL[0] + (y - 1)*qL[2],
y*qL[1] * qL[2] / qL[0] - (y - 1)*0.5*(qL[1] * qL[1] * qL[1]) / (qL[0] * qL[0]) };
cL2 = y * (y - 1)*(qL[2] / qL[0] - 0.5*(qL[1] / qL[0])*(qL[1] / qL[0]));
HL = 0.5*(qL[1] / qL[0])*(qL[1] / qL[0]) + cL2 / (y - 1);
uL = qL[1] / qL[0];
//Calculate Right side Parameters
//-------------------
double PR;
//double fqR[3];
double cR2;
double HR;
double uR;
PR = (y - 1)*(qR[2] - 0.5 / qR[0] * (qR[1] * qR[1]));
double fqR[3] = { qR[1],
(3 - y)*0.5*(qR[1] * qR[1]) / qR[0] + (y - 1)*qR[2],
y*qR[1] * qR[2] / qR[0] - (y - 1)*0.5*(qR[1] * qR[1] * qR[1]) / (qR[0] * qR[0]) };
cR2 = y * (y - 1)*(qR[2] / qR[0] - 0.5*(qR[1] / qR[0])*(qR[1] / qR[0]));
HR = 0.5*(qR[1] / qR[0])*(qR[1] / qR[0]) + cR2 / (y - 1);
uR = qR[1] / qR[0];
//-------------------
//Calculate Roe's Variables
//-------------------------------- -
double u;
double H;
double c;
double rho;
u = (sqrt(qL[1])*qL[2] / qL[1] + sqrt(qR[1])*qR[2] / qR[1]) / (sqrt(qL[1]) + sqrt(qR[1]));
H = (sqrt(qL[1])*HL + sqrt(qR[1])*HR) / (sqrt(qL[1]) + sqrt(qR[1]));
c = sqrt((y - 1)*(H - 0.5*u *u));
rho = sqrt(qL[1] * qR[1]);
//-------------------------------- -
//-------------------------------- -
double g[3] = { u - c, u, u + c };
double v[3][3] = { {1, u - c, H - u * c},
{1, u, 0.5*u*u},
{1, u + c, H + u * c } };
double a[3] = { 0.5 / (c*c)*((PR - PL) - c * rho*(uR - uL)),
(qR[0] - qL[0]) - 1 * (PR - PL) / (c*c),
0.5 / (c*c)*((PR - PL) + c * rho*(uR - uL)) };
double SUM[3];
SUM[0] = g[0] * a[0] * v[0][0] + g[1] * a[1] * v[1][0] + g[2] * a[2] * v[2][0];
SUM[1] = g[0] * a[0] * v[0][1] + g[1] * a[1] * v[1][1] + g[2] * a[2] * v[2][1];
SUM[2] = g[0] * a[0] * v[0][2] + g[1] * a[1] * v[1][2] + g[2] * a[2] * v[2][2];
double Flux[3];
Flux[0,i] = 0.5*(fqL[0] + fqR[0]) - 0.5*SUM[0];
Flux[1,i] = 0.5*(fqL[1] + fqR[1]) - 0.5*SUM[1];
Flux[2,i] = 0.5*(fqL[2] + fqR[2]) - 0.5*SUM[2];
std::cout << i << endl;
}
}

GL_TRIANGLES instead of GL_QUADS

I want to modify the code for generating 3D sphere, so it uses triangles for drawing instead of quads. The problem is, as usual, that I get some error -- "vector iterator not incrementable". What's wrong with it?
SolidSphere(float radius, unsigned int rings, unsigned int sectors)
{
float const R = 1.0f / (float)(rings-1);
float const S = 1.0f / (float)(sectors-1);
int r, s;
vertices.resize(rings * sectors * 3);
normals.resize(rings * sectors * 3);
texcoords.resize(rings * sectors * 2);
std::vector<GLfloat>::iterator v = vertices.begin();
std::vector<GLfloat>::iterator n = normals.begin();
std::vector<GLfloat>::iterator t = texcoords.begin();
for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) {
float const x = sinf(M_PI * r * R) * cosf(2 * M_PI * s * S);
float const y = sinf(-M_PI_2 + M_PI * r * R );
float const z = sinf(2.0f * M_PI * s * S) * sinf( M_PI * r * R );
*t++ = s*S;
*t++ = r*R;
*v++ = x * radius;
*v++ = y * radius;
*v++ = z * radius;
*n++ = x;
*n++ = y;
*n++ = z;
}
indices.resize(rings * sectors * 4);
std::vector<GLushort>::iterator i = indices.begin();
for(r = 0; r < rings-1; r++) for(s = 0; s < sectors-1; s++) {
/* triangles -- not working!
*i++ = r * sectors + s;
*i++ = (r + 1) * sectors + (s + 1);
*i++ = r * sectors + (s + 1);
*i++ = r * sectors + s;
*i++ = (r + 1) * sectors + s;
*i++ = (r + 1) * sectors + (s + 1); */
/* quads */
*i++ = r * sectors + s;
*i++ = r * sectors + (s+1);
*i++ = (r+1) * sectors + (s+1);
*i++ = (r+1) * sectors + s;
}
}
Looks like your triangle-generator-version of the loop does(sectors-1) times (rings-1) iterations, each one increasing i six times, but you have resized the vector i iterates through to just (rings * sectors * 4), which was enough to the quad-generator-version of the loop.
Assuming the triangle version was ok, this adjust shall fix it:
indices.resize(rings * sectors * 6)
This kind of oversight generally arises when you code without drinking enough coffee. Or too much of it (graph showing the hyperbola boundaries when your code will actually fail, (mapping rings and sectors numbers to x and y) due to the fact that you are allocating more space then needed for the iterations).

OpenGL sphere without GLUT and culling issue

I am modifying the excellent code provided in this answer Creating a 3D sphere in Opengl using Visual C++ to suit my needs, which is to draw it using GL_TRIANGLES and face culling like this:
GLCALL(glEnable(GL_CULL_FACE));
GLCALL(glCullFace(GL_BACK));
GLCALL(glFrontFace(GL_CCW));
I've managed to make the indices work for triangles, but I cant bloody figure out how to eliminate the cull face problem; as it is, it culls the wrong face using the indice setup I got below:
bool CreateSphereData(const float radius, const uint32_t rings, const uint32_t sectors, std::vector<float>& vertexData, std::vector<float>& normalData, std::vector<float>& texcoordData, std::vector<uint32_t>& indiceData)
{
if (radius <= 0 || rings <= 0 || sectors <= 0)
return false;
const float R = 1.0f / (float)(rings - 1);
const float S = 1.0f / (float)(sectors - 1);
const float pi = boost::math::constants::pi<float>();
const float pi_2 = pi / 2;
vertexData.resize(rings * sectors * 3);
normalData.resize(rings * sectors * 3);
texcoordData.resize(rings * sectors * 2);
auto v = vertexData.begin();
auto n = normalData.begin();
auto t = texcoordData.begin();
for (uint32_t r = 0; r < rings; r++)
{
for (uint32_t s = 0; s < sectors; s++)
{
const float y = sin(-pi_2 + pi * r * R);
const float x = cos(2 * pi * s * S) * sin(pi * r * R);
const float z = sin(2 * pi * s * S) * sin(pi * r * R);
*t++ = s*S;
*t++ = r*R;
*v++ = x * radius;
*v++ = y * radius;
*v++ = z * radius;
*n++ = x;
*n++ = y;
*n++ = z;
}
}
indiceData.resize(rings * sectors * 6);
auto i = indiceData.begin();
for (uint32_t r = 0; r < rings; r++)
{
for (uint32_t s = 0; s < sectors; s++)
{
*i++ = (r + 1) * sectors + s;
*i++ = r * sectors + s;
*i++ = r * sectors + (s + 1);
*i++ = (r + 1) * sectors + (s + 1);
*i++ = (r + 1) * sectors + s;
*i++ = r * sectors + (s + 1);
}
}
return true;
}
I am sure it is simple but I can't get it right. Any pointers?
EDIT/ANSWER:
Simply the following indices draws it correctly with setup mentioned above:
indiceData.resize(rings * sectors * 6);
auto i = indiceData.begin();
for (uint32_t r = 0; r < rings-1; r++)
{
for (uint32_t s = 0; s < sectors-1; s++)
{
*i++ = r * sectors + (s + 1);
*i++ = r * sectors + s;
*i++ = (r + 1) * sectors + s;
*i++ = r * sectors + (s + 1);
*i++ = (r + 1) * sectors + s;
*i++ = (r + 1) * sectors + (s + 1);
}
}