my program get infinite looping and I need the best solution.
the function I have is really linked to each others, so it might complicated to see.
where dt = 0.04, dx = 1 , a = 0.7, b = 0.4
the matters is to search p(x,t+1) need p(x,t), p(x-1,t) and p(x+1,t)
it also happen to other function.
public partial class Form1 : Form
{
double a,b,dt,dx;
public void JudulKolom() //to print in table, cause I planned to make p,q,n graphic using zedGraph
{
listView1.Columns.Add("t").Width =100;
listView1.Columns.Add("x").Width =100;
listView1.Columns.Add("p(x,t)").Width =100;
listView1.Columns.Add("q(x,t)").Width =100;
listView1.Columns.Add("n(x,t)").Width =100;
listView1.Columns.Add("r(x,t)").Width =100;
listView1.Columns.Add("c(x,t)").Width =100;
listView1.Columns.Add("f(c)").Width =100;
listView1.Columns.Add("g(c)").Width =100;
listView1.Columns.Add("h(c)").Width =100;
}
//fungsi p(x,t)
double fP (int x, double t)
{
double hasil = 0;
a = Convert.ToDouble(textBoxAlfa.Text);
if (t == 0) //for every t=0 and any x
{
hasil = 0.01 * Math.Exp(-0.1 * x);
}
else //for t=0.04 or t+1
{
if (x > 0) //for p when x=1..10 and t=0.04
{
hasil = fP(x,t-dt) + fD() * (fP(x+1,t-dt) - 2 * fP(x,t-dt) + fP(x-1,t-dt)) +
dt * fG(x,t-dt) * (1 - fR(x,t-dt)) - fF(x,t-dt) * fP(x,t-dt) + fP(x,t-dt) * Math.Sqrt(dt) * wiener(x);
}
else if (x == 0) //only for p when x=0 and t=0.04
{
hasil = fP(x,t-dt) + fD() * (fP(x+1,t-dt) - 2 * fP(x,t-dt) + fP(x,t-dt)) +
dt * fG(x,t-dt) * (1 - fR(x,t-dt)) - fF(x,t-dt) * fP(x,t-dt) + fP(x,t-dt) * Math.Sqrt(dt) * wiener(x);
}
}
return Math.Round(hasil, 6);
}
//fungsi q(x,t)
double fQ (int x, double t)
{
double hasil = 0;
if (t == 0) //for every q when t=0 and any x
{
hasil = 0;
}
else
{
if (x > 0) //for q when x=1..10 and t=0.04
{
hasil = fQ(x,t-dt) + fD() * (fQ(x+1,t-dt) - 2*fQ(x,t-dt) + fQ(x-1,t-dt)) +
dt * fF(x,t-dt) * fP(x,t-dt) -
(0.5 * fF(x,t-dt)) * fQ(x,t-dt);
}
else if (x == 0) //only for q when x=0 and t=0.04
{
hasil = fQ(x,t-dt) + fD() * (fQ(x+1,t-dt) - 2*fQ(x,t-dt) + fQ(x,t-dt)) +
dt * fF(x,t-dt) * fP(x,t-dt) -
(0.5 * fF(x,t-dt)) * fQ(x,t-dt);
}
}
return Math.Round(hasil, 6);
}
//fungsi n(x,t)
double fN (int x, double t)
{
double hasil=0;
if (t == 0) //for every n when t=0 and any x
{
hasil = 0;
}
else
{
if (x > 0) //only for n when x=1..10 and t=0.04
{
hasil = fN(x,t-dt) + dt * (0.5 * fF(x,t-dt)) * fQ(x,t-dt);
}
else if (x == 0) //only for n when x=0 and t=0.04
{
hasil = fN(x,t-dt) + dt * (0.5 * fF(x,t-dt)) * fQ(x,t-dt);
}
}
return Math.Round(hasil, 6);
}
//fungsi r(x,t)
double fR (int x, double t)
{
double hasil = 0;
hasil = fP(x,t) + fQ(x,t) + fN(x,t); //for every any x and t
return Math.Round(hasil, 6);
}
//fungsi c(x,t)
double fC (int x, double t)
{
double hasil = 0;
a = Convert.ToDouble(textBoxAlfa.Text);
if (t == 0) //for every C when t=0 and any x
{
hasil = ((1.0 * 10) / (10 + fP(x,t)))*(1.0 - a * fR(x,t)); //the matter is the R function that I have to use fR value in fC(c,t=0) when I look for fC(x,t=0.04)
}
else if (t != 0) //for every C when t is not 0 and any x
{
hasil = ((1.0 * 10) / (10 + fP(x,t-dt)))*(1.0 - a * fR(x,t-dt));
}
return Math.Round(hasil, 6);
}
//fungsi f(c)
double fF (int x, double t)
{
double hasil = 0;
if (t == 0) //for every F when t=0 and any x
{
hasil = 0.5 * (1-Math.Tanh(4 * fC(x,t) - 2));
}
else if (t != 0) //for every F when t is not 0 and any x
{
hasil = 0.5 * (1-Math.Tanh(4 * fC(x,t-dt) - 2));
}
return Math.Round(hasil, 6);
}
//fungsi g(c)
double fG (int x, double t)
{
double hasil = 0;
b = Convert.ToDouble(textBoxBeta.Text);
if (t == 0) //for every G when t=0 and any x
{
hasil = b * Math.Exp(b * fC(x,t));
}
else if (t != 0) //for every G when t is not 0 and any x
{
hasil = b * Math.Exp(b * fC(x,t-dt));
}
return Math.Round(hasil, 6);
}
//fungsi h(c)
double fH (double f) //only for q when x=0 and t=0.04
{
double hasil = 0;
hasil = 0.5 * f;
return Math.Round(hasil, 6);
}
double fD ()
{
double hasil = 0;
hasil = 1.0 * dt / (dx * dx);
return Math.Round(hasil, 6);
}
double wiener (int x)
{
double hasil = 0, dt = 0.04, Pi = 3.14159265358979;
hasil = 1.0 / Math.Sqrt(2 * Pi * dt) * Math.Exp(-1.0 * Math.Pow(x,2) / (2 * dt));
return Math.Round(hasil, 6);
}
private void button1_Click(object sender, EventArgs e)
{
if (textBoxAlfa.Text == "" || textBoxBeta.Text == "" || tbXvalue.Text == "" || tbTvalue.Text == "")
{
MessageBox.Show("Semua input harus diisi angka!");
}
else
{
double p=0,q=0,n=0;
double r,a,c,f,g,h,t;
int x;
a = Convert.ToDouble(textBoxAlfa.Text);
b = Convert.ToDouble(textBoxBeta.Text);
t = Convert.ToDouble(tbTvalue.Text);
x = Convert.ToInt32(tbXvalue.Text);
dt=0.04;
dx=1;
int indeks=-1;
while (t<=0.08)
{
x = 0;
for(int i=0; i<=10; i++)
{
listView1.Items.Add(t.ToString());
indeks=indeks+1;
p=fP(x,t);
q=fQ(x,t);
n=fN(x,t);
r=fR(x,t);
c=fC(x,t);
f=fF(x,t);
g=fG(x,t);
h=fH(f);
listView1.Items[indeks].SubItems.Add(x.ToString());
listView1.Items[indeks].SubItems.Add(p.ToString());
listView1.Items[indeks].SubItems.Add(q.ToString());
listView1.Items[indeks].SubItems.Add(n.ToString());
listView1.Items[indeks].SubItems.Add(r.ToString());
listView1.Items[indeks].SubItems.Add(c.ToString());
listView1.Items[indeks].SubItems.Add(f.ToString());
listView1.Items[indeks].SubItems.Add(g.ToString());
listView1.Items[indeks].SubItems.Add(h.ToString());
}
t=t+0.04;
JudulKolom();
}
}
}
you should not compare floating point numbers by equating. You need to allow some imprecision. something like if (Math.Abs(a - b) < epsilon) {} Change your checking if (t == 0) to if (Math.Abs(t) < 0.00001) or some allowed small number.
I think, dt in your formulas is defined for this.
Related
I am trying to implement the algorithm described in the following http://repositorium.sdum.uminho.pt/bitstream/1822/6429/1/ConcaveHull_ACM_MYS.pdf
I am using the following class libraries. Loyc libs come from http://core.loyc.net/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Device.Location;
using Loyc.Collections;
using Loyc.Geometry;
using Loyc;
Here is the basic class
public class Hulls
{
private static List<Point<double>> KNearestNeighbors(List<Point<double>> points, Point<double> currentPoint, int k, out int kk)
{
kk = Math.Min(k, points.Count - 1);
var ret = points
.OrderBy(x => PointMath.Length(new Vector<double>(currentPoint.X - x.X, currentPoint.Y - x.Y)))
.Take(k)
.ToList();
return ret;
}
private static double Angle(Point<double> a, Point<double> b)
{
var ret = -Math.Atan2(b.Y - a.Y, b.X - a.X);
return NormaliseAngle(ret);
}
private static double NormaliseAngle(double a)
{
//while (a < b - Math.PI) a += Math.PI * 2;
//while (b < a - Math.PI) b += Math.PI * 2;
if (a < 0.0) { return a + Math.PI + Math.PI; }
return a;
}
private static List<Point<double>> SortByAngle(List<Point<double>> kNearest, Point<double> currentPoint, double angle)
{
//kNearest
// .Sort((v1, v2) => AngleDifference(angle, Angle(currentPoint, v1)).CompareTo(AngleDifference(angle, Angle(currentPoint, v2))));
//return kNearest.ToList();
kNearest = kNearest.OrderByDescending(x => NormaliseAngle(Angle(currentPoint, x) - angle)).ToList();
return kNearest;
}
private static bool CCW(Point<double> p1, Point<double> p2, Point<double> p3)
{
var cw = ((p3.Y - p1.Y) * (p2.X - p1.X)) - ((p2.Y - p1.Y) * (p3.X - p1.X));
return cw > 0 ? true : cw < 0 ? false : true; // colinear
}
private static bool _Intersect(LineSegment<double> seg1, LineSegment<double> seg2)
{
return CCW(seg1.A, seg2.A, seg2.B) != CCW(seg1.B, seg2.A, seg2.B) && CCW(seg1.A, seg1.B, seg2.A) != CCW(seg1.A, seg1.B, seg2.B);
}
private static bool Intersect(LineSegment<double> seg1, LineSegment<double> seg2)
{
if ((seg1.A.X == seg2.A.X && seg1.A.Y == seg2.A.Y)
|| (seg1.B.X == seg2.B.X && seg1.B.Y == seg2.B.Y))
{
return false;
}
if (_Intersect(seg1, seg2))
{
return true;
}
return false;
}
public IListSource<Point<double>> KNearestConcaveHull(List<Point<double>> points, int k)
{
points.Sort((a, b) => a.Y == b.Y ? (a.X > b.X ? 1 : -1) : (a.Y >= b.Y ? 1 : -1));
Console.WriteLine("Starting with size {0}", k.ToString());
DList<Point<double>> hull = new DList<Point<double>>();
var len = points.Count;
if (len < 3) { return null; }
if (len == 3) { return hull; }
var kk = Math.Min(Math.Max(k, 3), len);
var dataset = new List<Point<double>>();
dataset.AddRange(points.Distinct());
var firstPoint = dataset[0];
hull.PushFirst(firstPoint);
var currentPoint = firstPoint;
dataset.RemoveAt(0);
double previousAngle = 0;
int step = 2;
int i;
while ((currentPoint != firstPoint || step == 2) && dataset.Count > 0)
{
if (step == 5) { dataset.Add(firstPoint); }
var kNearest = KNearestNeighbors(dataset, currentPoint, k, out kk);
var cPoints = SortByAngle(kNearest, currentPoint, previousAngle);
var its = true;
i = 0;
while (its == true && i < cPoints.Count)
{
i++;
int lastPoint = 0;
if (cPoints[i - 1] == firstPoint)
{
lastPoint = 1;
}
int j = 2;
its = false;
while (its == false && j < hull.Count - lastPoint)
{
LineSegment<double> line1 = new LineSegment<double>(hull[step - 2], cPoints[i - 1]);
LineSegment<double> line2 = new LineSegment<double>(hull[step - 2 - j], hull[step - 1 - j]);
//its = LineMath.ComputeIntersection(line1, line2, out pfrac, LineType.Segment);
its = Intersect(line1, line2);
j++;
}
}
if (its == true)
{
return KNearestConcaveHull(points, kk + 1);
}
currentPoint = cPoints[i - 1];
hull.PushLast(currentPoint);
previousAngle = Angle(hull[step - 1], hull[step - 2]);
dataset.Remove(currentPoint);
step++;
}
bool allInside = true;
i = dataset.Count;
while (allInside == true && i > 0)
{
allInside = PolygonMath.IsPointInPolygon(hull, dataset[i - 1]);
i--;
}
if (allInside == false) { return KNearestConcaveHull(points, kk + 1); }
return hull;
}
}
The above is supposed to pick a new edge for the boundary based on the furthest right-hand turn from the previous edge going around the point set counterclockwise. The code seems to pick the correct first edge from the initial vertex which has the lowest y-value, but then does not pick the next edge correctly when the offset angle is nonzero. I think the issue is the SortByAngle or Angle. -atan2 would return the clockwise turn, correct? Possibly I should be adding the offset angle?
EDIT (SOLUTION): Found the issue after following Eric's helpful advice provided in the first comment to the question. It was SortByAngle and Angle:
private static double Angle(Point<double> a, Point<double> b)
{
var ret = Math.Atan2(b.Y - a.Y, b.X - a.X);
return NormaliseAngle(ret);
}
private static double NormaliseAngle(double a)
{
if (a < 0.0) { return a + Math.PI + Math.PI; }
return a;
}
private static List<Point<double>> SortByAngle(List<Point<double>> kNearest, Point<double> currentPoint, double angle)
{
//kNearest = kNearest.OrderByDescending(x => NormaliseAngle(Angle(currentPoint, x) - angle)).ToList();
kNearest.Sort((a, b) => NormaliseAngle(Angle(currentPoint, a) - angle) > NormaliseAngle(Angle(currentPoint, b) - angle) ? 1 : -1);
return kNearest;
}
You have some bug:
var kNearest = KNearestNeighbors(dataset, currentPoint, k, out kk);
Change the kk to just some var. You override the incrementation of that "kk" value, and then you're getting StackOverflow exceptions.
Change your code to the following:
int someVal;
var kNearest = KNearestNeighbors(dataset, currentPoint, k, out someVal);
I'm trying to add x and y data in text file like all the x result line by line and y results next to x for example ; 40,281516651,1,17956575 . But in this codes overwriting the results to many times because of the foreach.
double z, d, x, k, y;
d = double.Parse(textBox1.Text);
for (double i = 0; i <= 90; i++)
{
k = Math.PI / 180;
z = Math.Tan((i / 2 + 45) * k);
x = (d / 3.141) * (Math.Sin(Math.PI * i / 180) - Math.Log(z));
y = d / 3.141 * (Math.Cos((Math.PI * i) / 180) + (3.141 / 2));
listBox2.Items.Add(x);
listBox1.Items.Add(y);
listBox3.Items.Add(z);
const string sPath = #"C:\Users\NET\Desktop\deneme.txt";
StreamWriter SaveFile = new StreamWriter(sPath);
foreach (var item in listBox1.Items)
{
SaveFile.WriteLine(item);
foreach (var a in listBox2.Items)
{
SaveFile.WriteLine(a);
}
}
SaveFile.Close();
}
}
}
}
//fill the listBoxes
for (double i = 0; i <= 90; i++)
{
k = Math.PI / 180;
z = Math.Tan((i / 2 + 45) * k);
x = (d / 3.141) * (Math.Sin(Math.PI * i / 180) - Math.Log(z));
y = d / 3.141 * (Math.Cos((Math.PI * i) / 180) + (3.141 / 2));
listBox2.Items.Add(x);
listBox1.Items.Add(y);
listBox3.Items.Add(z);
}
// write the text file
const string sPath = #"C:\Users\NET\Desktop\deneme.txt";
using(StreamWriter SaveFile = new StreamWriter(sPath))
{
for (int i=0; i<listBox1.Items.Count; i++)
{
string line = String.Format("{0},{1}", listBox1.Items[i], listBox2.Items[i]);
SaveFile.WriteLine(line);
}
}
Don't nest your loops, but haver them one after the next:
for (int i = 0; i <= 90; i++)
{
...
listBox2.Items.Add(x);
listBox1.Items.Add(y);
listBox3.Items.Add(z);
}
...
foreach (var item in listBox1.Items)
{
SaveFile.WriteLine(item);
}
foreach (var a in listBox2.Items)
{
SaveFile.WriteLine(a);
}
I purchased the book Numerical Methods, Algorithms and Tools in C# by Waldemar Dos Passos.
On page 463, there is the method:
public static double FactorialLn(int n)
{
if(n < 0)
{
throw new Exception("Input value must be > 0");
}
else
{
return GammaLn(n+1.0);
}
}
I found the namespace where the function GammaLn resides: MicrosoftResearch.Infer.Maths
but Visual Studio 2010 does not recognize it and I was unable to find it in the .NET reference.
Please help me get the program to compile.
Thank you in advance.
I finally found the dource code of the GammaLn method itself here: http://seungwon.tistory.com/9
One does need nothing else when one possesses the very real thing, as Andrey correctly pointed out, but until then ...
I reproduce the method here for future reference, in case the site above stops from functioning.
/// <summary>
/// http://seungwon.tistory.com/9
/// GammaLn函数
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
public static double GammaLn(double x)
{
double result = 0.0;
double d1 = -5.772156649015328605195174e-1;
double[,] p1 = {{4.945235359296727046734888e0},{ 2.018112620856775083915565e2},
{2.290838373831346393026739e3},{ 1.131967205903380828685045e4},
{2.855724635671635335736389e4},{ 3.848496228443793359990269e4},
{2.637748787624195437963534e4},{ 7.225813979700288197698961e3}};
double[,] q1 = {{6.748212550303777196073036e1},{ 1.113332393857199323513008e3},
{7.738757056935398733233834e3},{ 2.763987074403340708898585e4},
{5.499310206226157329794414e4},{ 6.161122180066002127833352e4},
{3.635127591501940507276287e4},{ 8.785536302431013170870835e3}};
double d2 = 4.227843350984671393993777e-1;
double[,] p2 = {{4.974607845568932035012064e0},{ 5.424138599891070494101986e2},
{1.550693864978364947665077e4},{ 1.847932904445632425417223e5},
{1.088204769468828767498470e6},{ 3.338152967987029735917223e6},
{5.106661678927352456275255e6},{ 3.074109054850539556250927e6}};
double[,] q2 = {{1.830328399370592604055942e2},{ 7.765049321445005871323047e3},
{1.331903827966074194402448e5},{ 1.136705821321969608938755e6},
{5.267964117437946917577538e6},{ 1.346701454311101692290052e7},
{1.782736530353274213975932e7},{ 9.533095591844353613395747e6}};
double d4 = 1.791759469228055000094023e0;
double[,] p4 = {{1.474502166059939948905062e4},{ 2.426813369486704502836312e6},
{1.214755574045093227939592e8},{ 2.663432449630976949898078e9},
{2.940378956634553899906876e10},{ 1.702665737765398868392998e11},
{4.926125793377430887588120e11},{5.606251856223951465078242e11}};
double[,] q4 = {{2.690530175870899333379843e3},{ 6.393885654300092398984238e5},
{4.135599930241388052042842e7},{ 1.120872109616147941376570e9},
{1.488613728678813811542398e10},{1.016803586272438228077304e11},
{3.417476345507377132798597e11},{ 4.463158187419713286462081e11}};
double[,] c = {{-1.910444077728e-03},{ 8.4171387781295e-04},
{-5.952379913043012e-04},{ 7.93650793500350248e-04},
{-2.777777777777681622553e-03},{ 8.333333333333333331554247e-02},
{ 5.7083835261e-03}};
double eps = 2.2204e-016;
if (x <= 0)
{
//报错!
}
else
{
double xden = 0.0;
double xnum = 0.0;
result = x;
if (x > 0 && x <= eps)
{
result = -Math.Log(x);
}
else if ((x > eps) && (x <= 0.5))
{
double y = x;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * y + p1[i, 0];
xden = xden * y + q1[i, 0];
}
result = -Math.Log(y) + (y * (d1 + y * (xnum / xden)));
}
else if ((x > 0.5) && (x <= 0.6796875))
{
double xm1 = (x - 0.5) - 0.5;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm1 + p2[i, 0];
xden = xden * xm1 + q2[i, 0];
}
result = -Math.Log(x) + xm1 * (d2 + xm1 * (xnum / xden));
}
else if ((x > 0.6796875) && (x <= 1.5))
{
double xm1 = (x - 0.5) - 0.5;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm1 + p1[i, 0];
xden = xden * xm1 + q1[i, 0];
}
result = xm1 * (d1 + xm1 * (xnum / xden));
}
else if ((x > 1.5) && (x <= 4))
{
double xm2 = x - 2;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm2 + p2[i, 0];
xden = xden * xm2 + q2[i, 0];
}
result = xm2 * (d2 + xm2 * (xnum / xden));
}
else if ((x > 4) && (x <= 12))
{
double xm4 = x - 4;
xden = -1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm4 + p4[i, 0];
xden = xden * xm4 + q4[i, 0];
}
result = d4 + xm4 * (xnum / xden);
}
else if (x > 12)
{
double y = x;
double r = c[6, 0];// 等于:double r = repmat(c[6, 0], 1)[0,0];
double ysq = y * y;
for (int i = 0; i < 6; i++)
{
r = r / ysq + c[i, 0];
}
r = r / y;
double corr = Math.Log(y);
double spi = 0.9189385332046727417803297;
result = r + spi - 0.5 * corr + y * (corr - 1);
}
}
return result;
}
similarly to the question: Inverted beta in MySQL I need to use the BetaInv function inside a SQL Server stored procedure.
function is described here: Excel's BETAINV
is anybody aware of anything similar in TSQL or would you wrap it in a CLR .NET managed SQL user defined function?
I really need to use it within the stored procedure and not as post executing code in the C# side after data has been retrieved with the stored procedure because I should keep all logic on the db server for better reuse.
can I assume that a .NET managed udf running in the SQL Server would perform as fast as a normal native TSQL function?
Thanks!
I've in the end implemented the whole function myself, here the source code in case somebody needs it:
public static class UDFs
{
private const int MAXIT = 100;
private const double EPS = 0.0000003;
private const double FPMIN = 1.0E-30;
[SqlFunction(Name = "BetaInv", DataAccess = DataAccessKind.Read)]
public static SqlDouble BetaInv(SqlDouble p, SqlDouble alpha, SqlDouble beta, SqlDouble A, SqlDouble B)
{
return InverseBeta(p.Value, alpha.Value, beta.Value, A.Value, B.Value);
}
private static double InverseBeta(double p, double alpha, double beta, double A, double B)
{
double x = 0;
double a = 0;
double b = 1;
double precision = Math.Pow(10, -6); // converge until there is 6 decimal places precision
while ((b - a) > precision)
{
x = (a + b) / 2;
if (IncompleteBetaFunction(x, alpha, beta) > p)
{
b = x;
}
else
{
a = x;
}
}
if ((B > 0) && (A > 0))
{
x = x * (B - A) + A;
}
return x;
}
private static double IncompleteBetaFunction(double x, double a, double b)
{
double bt = 0;
if (x <= 0.0)
{
return 0;
}
if (x >= 1)
{
return 1;
}
bt = System.Math.Exp(Gammln(a + b) - Gammln(a) - Gammln(b) + a * System.Math.Log(x) + b * System.Math.Log(1.0 - x));
if (x < ((a + 1.0) / (a + b + 2.0)))
{
// Use continued fraction directly.
return (bt * betacf(a, b, x) / a);
}
else
{
// Use continued fraction after making the symmetry transformation.
return (1.0 - bt * betacf(b, a, 1.0 - x) / b);
}
}
private static double betacf(double a, double b, double x)
{
int m, m2;
double aa, c, d, del, h, qab, qam, qap;
qab = a + b; // These q’s will be used in factors that occur in the coe.cients (6.4.6).
qap = a + 1.0;
qam = a - 1.0;
c = 1.0; // First step of Lentz’s method.
d = 1.0 - qab * x / qap;
if (System.Math.Abs(d) < FPMIN)
{
d = FPMIN;
}
d = 1.0 / d;
h = d;
for (m = 1; m <= MAXIT; ++m)
{
m2 = 2 * m;
aa = m * (b - m) * x / ((qam + m2) * (a + m2));
d = 1.0 + aa * d; //One step (the even one) of the recurrence.
if (System.Math.Abs(d) < FPMIN)
{
d = FPMIN;
}
c = 1.0 + aa / c;
if (System.Math.Abs(c) < FPMIN)
{
c = FPMIN;
}
d = 1.0 / d;
h *= d * c;
aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
d = 1.0 + aa * d; // Next step of the recurrence (the odd one).
if (System.Math.Abs(d) < FPMIN)
{
d = FPMIN;
}
c = 1.0 + aa / c;
if (System.Math.Abs(c) < FPMIN)
{
c = FPMIN;
}
d = 1.0 / d;
del = d * c;
h *= del;
if (System.Math.Abs(del - 1.0) < EPS)
{
// Are we done?
break;
}
}
if (m > MAXIT)
{
return 0;
}
else
{
return h;
}
}
public static double Gammln(double xx)
{
double x, y, tmp, ser;
double[] cof = new double[] { 76.180091729471457, -86.505320329416776, 24.014098240830911, -1.231739572450155, 0.001208650973866179, -0.000005395239384953 };
y = xx;
x = xx;
tmp = x + 5.5;
tmp -= (x + 0.5) * System.Math.Log(tmp);
ser = 1.0000000001900149;
for (int j = 0; j <= 5; ++j)
{
y += 1;
ser += cof[j] / y;
}
return -tmp + System.Math.Log(2.5066282746310007 * ser / x);
}
}
}
as you can see in the code, the SqlFunction is calling the InverseBeta private method which does the job using couple of other methods.
results are the same of Excel.BetaInv up to 5 or 6 digits after comma.
I'm trying to convert a RGB32 value to HSL because I want to use the Hue component.
I have used some examples that I found online to create this class:
public class HSLColor
{
public Double Hue;
public Double Saturation;
public Double Luminosity;
public HSLColor(Double H, Double S, Double L)
{
Hue = H;
Saturation = S;
Luminosity = L;
}
public static HSLColor FromRGB(Color Clr)
{
return FromRGB(Clr.R, Clr.G, Clr.B);
}
public static HSLColor FromRGB(Byte R, Byte G, Byte B)
{
Double _R = (R / 255d);
Double _G = (G / 255d);
Double _B = (B / 255d);
Double _Min = Math.Min(Math.Min(_R, _G), _B);
Double _Max = Math.Max(Math.Max(_R, _G), _B);
Double _Delta = _Max - _Min;
Double H = 0;
Double S = 0;
Double L = (float)((_Max + _Min) / 2.0f);
if (_Delta != 0)
{
if (L < 0.5d)
{
S = (float)(_Delta / (_Max + _Min));
}
else
{
S = (float)(_Delta / (2.0f - _Max - _Min));
}
if (_R == _Max)
{
H = (_G - _B) / _Delta;
}
else if (_G == _Max)
{
H = 2f + (_B - _R) / _Delta;
}
else if (_B == _Max)
{
H = 4f + (_R - _G) / _Delta;
}
}
//Convert to degrees
H = H * 60d;
if (H < 0) H += 360;
//Convert to percent
S *= 100d;
L *= 100d;
return new HSLColor(H, S, L);
}
private Double Hue_2_RGB(Double v1, Double v2, Double vH)
{
if (vH < 0) vH += 1;
if (vH > 1) vH -= 1;
if ((6.0d * vH) < 1) return (v1 + (v2 - v1) * 6 * vH);
if ((2.0d * vH) < 1) return (v2);
if ((3.0d * vH) < 2) return (v1 + (v2 - v1) * ((2.0d / 3.0d) - vH) * 6.0d);
return (v1);
}
public Color ToRGB()
{
Color Clr = new Color();
Double var_1, var_2;
if (Saturation == 0)
{
Clr.R = (Byte)(Luminosity * 255);
Clr.G = (Byte)(Luminosity * 255);
Clr.B = (Byte)(Luminosity * 255);
}
else
{
if (Luminosity < 0.5) var_2 = Luminosity * (1 + Saturation);
else var_2 = (Luminosity + Saturation) - (Saturation * Luminosity);
var_1 = 2 * Luminosity - var_2;
Clr.R = (Byte)(255 * Hue_2_RGB(var_1, var_2, Hue + (1 / 3)));
Clr.G = (Byte)(255 * Hue_2_RGB(var_1, var_2, Hue));
Clr.B = (Byte)(255 * Hue_2_RGB(var_1, var_2, Hue - (1 / 3)));
}
return Clr;
}
}
However it doesn't seem to work correctly,
If I use an input color of (R 0, G 255, B 193) for example:
I get Hue = 0
while in photoshop if I choose the exact same RGB values I get:
Hue = 165
which is the correct value.
I want the Hue to be a value ranging from 0 to 360 or 0 to 240
What is the problem?..
Reference:
EasyRGB RGB->HSL
R / 255
this is integer division, meaning you get either 0 or 1. try:
(float)R / 255
and for all other cases.
for constants try:
( 1 / 3 ) -> ( 1.0 / 3.0 )
The below is open source mixture of Drupal + some various programmers work mixed into one single function boasting RGB > HSL and back. It works flawlessly.
<?php
### RGB >> HSL
function _color_rgb2hsl($rgb) {
$r = $rgb[0]; $g = $rgb[1]; $b = $rgb[2];
$min = min($r, min($g, $b)); $max = max($r, max($g, $b));
$delta = $max - $min; $l = ($min + $max) / 2; $s = 0;
if ($l > 0 && $l < 1) {
$s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l));
}
$h = 0;
if ($delta > 0) {
if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
$h /= 6;
} return array($h, $s, $l);
}
### HSL >> RGB
function _color_hsl2rgb($hsl) {
$h = $hsl[0]; $s = $hsl[1]; $l = $hsl[2];
$m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s;
$m1 = $l * 2 - $m2;
return array(_color_hue2rgb($m1, $m2, $h + 0.33333),
_color_hue2rgb($m1, $m2, $h),
_color_hue2rgb($m1, $m2, $h - 0.33333));
}
### Helper function for _color_hsl2rgb().
function _color_hue2rgb($m1, $m2, $h) {
$h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h);
if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
if ($h * 2 < 1) return $m2;
if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6;
return $m1;
}
### Convert a hex color into an RGB triplet.
function _color_unpack($hex, $normalize = false) {
if (strlen($hex) == 4) {
$hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
} $c = hexdec($hex);
for ($i = 16; $i >= 0; $i -= 8) {
$out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
} return $out;
}
### Convert an RGB triplet to a hex color.
function _color_pack($rgb, $normalize = false) {
foreach ($rgb as $k => $v) {
$out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8));
}return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
}
print "Hex: ";
$testhex = "#b7b700";
print $testhex;
$testhex2rgb = _color_unpack($testhex,true);
print "<br />RGB: ";
var_dump($testhex2rgb);
print "<br />HSL color module: ";
$testrgb2hsl = _color_rgb2hsl($testhex2rgb); //Convert to HSL
var_dump($testrgb2hsl);
print "<br />RGB: ";
$testhsl2rgb = _color_hsl2rgb($testrgb2hsl); // And back to RGB
var_dump($testhsl2rgb);
print "<br />Hex: ";
$testrgb2hex = _color_pack($testhsl2rgb,true);
var_dump($testrgb2hex);
?>