RGB to HSL, hue calculation is wrong - c#

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);
?>

Related

How to return two list with a double method? [duplicate]

This question already has answers here:
Return multiple values to a method caller
(28 answers)
Closed 3 years ago.
I'm working on a C# program that getting some values from textboxes and set them to some variables in 2 class that their name is:"Tfluid" and "Twell"
then I use them in another class the name is "Tcalc" through a method with name "fluidcal" and make some calculations with them,
I have 2 crossed while that means it starts with a "ql" and then match a final P to each "ql". now I want to use these (ql, P) to plot a graph in another form,
so what is the best way of saving them
(i don't know what should I return with the fluidal method)
and how can I add them to the chart?
this is my calculation process
public double Fluidcal(TWell well, TFluid fluid)
{
double froudnumber, noslipholdup, vm, vsl, vsg, liquidvelocitynumber, l1, l2, l3, l4, fluidregim, hozhold, C, psy, liqhold, liqholdseg, liqholdinter, fn, nren, densityn, viscosityn, y, S, ftp, dpdzel, dpdzf, dpperdzt, rhos, Ek,ql;
ql = 1;
while (ql<=fluid.maxoilflowrate)
{
vsl = (ql) / Math.PI * Math.Pow(well.tubingdiameter / 2, 2); //superficial velocities
vsg = (ql * fluid.gor) / Math.PI * Math.Pow(well.tubingdiameter / 2, 2);
vm = vsl + vsg;
double nowlength = 0;
double P = well.wellheadpressure;
while (nowlength <= well.welldepth)
{
froudnumber = Math.Pow(vm, 2) / well.tubingdiameter * 32.174; //froud number
noslipholdup = vsl / vm; //no slip holdup
double newoildensity = fluid.oildensity / (1 + 0.00056 * (0.01515 * nowlength));
liquidvelocitynumber = vsl * Math.Pow((newoildensity / 32.174 * fluid.gasliquidsurfacetension), 0.25); //liquid velocity number
//correlating parametrs
l1 = 316 * Math.Pow(noslipholdup, 0.302);
l2 = 0.0009252 * Math.Pow(noslipholdup, -2.4684);
l3 = 0.1 * Math.Pow(noslipholdup, -1.4516);
l4 = 0.5 * Math.Pow(noslipholdup, -6.738);
fluidregim = 0;
C = 0;
liqhold = 0;
if ((noslipholdup < 0.01 && froudnumber < l1) || (noslipholdup >= 0.01 && froudnumber < l2))
{
segregated(froudnumber, noslipholdup, liquidvelocitynumber, out fluidregim, out hozhold, out C, out psy, out liqhold);
}
else if ((noslipholdup >= 0.01 && l2 < froudnumber && froudnumber <= l3))
{
transition(froudnumber, noslipholdup, liquidvelocitynumber, l2, l3, out fluidregim, out hozhold, out C, out psy, out liqhold, out liqholdseg, out liqholdinter);
}
else if ((noslipholdup >= 0.01 && noslipholdup < 0.4 && froudnumber > l3 && froudnumber <= l1)
|| (noslipholdup >= 0.4 && l3 < froudnumber && froudnumber <= 4))
{
intermittent(froudnumber, noslipholdup, liquidvelocitynumber, out fluidregim, out hozhold, out C, out psy, out liqhold);
}
else if ((noslipholdup < 0.4 && froudnumber >= l1) || (noslipholdup >= 0.4 && froudnumber > l4))
{
disturbuted(froudnumber, noslipholdup, out fluidregim, out hozhold, out C, out psy, out liqhold);
}
// else
// {
// System.Windows.Forms.MessageBox.Show("Undefined Flow Regim");
//}
y = noslipholdup / Math.Pow(liqhold, 2);
if (y > 1 && y < 1.2)
{
S = Math.Log(2.2 * y - 1.2);
}
else
{
S = (Math.Log(y)) / (-0.0523 + 3.182 * Math.Log(y) - 0.8725 * Math.Pow(Math.Log(y), 2) + 0.01853 * Math.Pow(Math.Log(y), 4));
}
viscosityn = fluid.oilviscosity * noslipholdup + fluid.gasviscosity * (1 - noslipholdup);
densityn = fluid.oildensity * noslipholdup + (1 - noslipholdup) * fluid.gasdensity;
nren = densityn * vm * (well.tubingdiameter) / viscosityn;
fn = 1 / Math.Pow((2 * Math.Log(nren / (4.5223 * Math.Log(nren) - 3.8215))), 2);
ftp = fn * Math.Exp(S);
rhos = fluid.oildensity * liqhold + fluid.gasdensity * (1 - liqhold);
Ek = rhos * vm * vsg / 32.2 * P;
dpdzel = (1) * rhos;
dpdzf = ftp * densityn * Math.Pow(vm, 2) / 2 * 32.174 * well.tubingdiameter;
dpperdzt = (dpdzel + dpdzf) / 1 - Ek;
P = P + 5 * dpperdzt;
yax.Add(P);
nowlength = +5;
vsl = vm * liqhold;
vsg = vsl * fluid.gor;
}
ql = +20;
}return; //what should I write here?I want pairs of(ql,P)
There are a few ways you could do this. I would suggest encapsulating the lists in an object and returning that object from your method. For example:
public class MyLists
{
public List<double> ListOne { get; set; }
public List<double> ListTwo { get; set; }
}
Of course, you could use a Tuple. If I understand your question correctly...

Refactor multiple goto statements from the loop body

I am struggling to replicate the following fortran 77 subroutine into C# method. The main problem is that I am trying to get rid of the fortran's goto statements.
The fortran to C# conversion looks fine, still the goto statements remained. Is there a way all of them can be replaced with conditionals or some other ways? Thank you.
Here is the fortran subroutine:
C PROGRAM TEMP
subroutine TEMP (acl,adu,aeff,c,cair,cb,cbare,
+ cclo,count1,csum,di,ed,emcl,emsk,enbal,
+ enbal2,ere,erel,esw,eswdif,eswphy,eswpot,
+ evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,j,
+ mbody,p,po,r1,r2,rbare,rcl,
+ rclo,rclo2,rdcl,rdsk,rob,rsum,sex,sigm,sw,swf,swm,
+ ta,tbody,tcl,tcore,tmrt,tsk,v,vb,vb1,vb2,
+ vpa,vpts,wetsk,wd,wr,ws,wsum,xx)
real acl,adu,aeff,c(0:10),cair,cb,cbare,
+ cclo,csum,di,ed,emcl,emsk,enbal,
+ enbal2,ere,erel,esw,eswdif,eswphy,eswpot,
+ evap,facl,fcl,fec,feff,food,h,hc,he,ht,htcl,icl,
+ mbody,p,po,r1,r2,rbare,rcl,
+ rclo,rclo2,rdcl,rdsk,rob,rsum,sigm,sw,swf,swm,
+ ta,tbody,tcl,tcore(1:7),tmrt,tsk,v,vb,vb1,vb2,
+ vpa,vpts,wetsk,wd,wr,ws,wsum,xx
integer count1,count3,j,sex
wetsk = 0.
adu = 0.203 * mbody ** 0.425 * ht ** 0.725
hc = 2.67 + ( 6.5 * v ** 0.67)
hc = hc * (p /po) ** 0.55
feff = 0.725
C
facl = (- 2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28
+ * (icl ** 3.)) / 100.
C
if (facl .gt.1.) facl = 1.
rcl = (icl/6.45)/facl
if (icl.ge.2.) y = 1.
if ((icl .gt. 0.6) .and. (icl .lt. 2.)) y = (ht - 0.2) / ht
if ((icl .le. 0.6) .and. (icl .gt. 0.3)) y = 0.5
if ((icl .le. 0.3) .and. (icl .gt. 0.)) y = 0.1
r2 = adu * (fcl - 1. + facl) / (2. * 3.14 * ht * y)
r1 = facl * adu / (2. * 3.14 * ht * y)
di = r2 - r1
C TEMPERATURE
do 90 j = 1,7
tsk = 34.
count1 = 0
tcl = (ta + tmrt + tsk) / 3.
count3 = 1
enbal2 = 0.
20 acl = adu * facl + adu * (fcl - 1.)
rclo2 = emcl*sigm *((tcl+273.2)** 4.-(tmrt+273.2)** 4.)*feff
htcl = 6.28 * ht * y * di / (rcl * alog(r2/r1) * acl)
tsk = 1. / htcl * (hc * (tcl - ta) + rclo2) + tcl
C RADIATION
aeff = adu * feff
rbare = aeff * (1.-facl) * emsk * sigm *
+ ((tmrt + 273.2) ** 4. - (tsk + 273.2) ** 4.)
rclo = feff * acl * emcl * sigm *
+ ((tmrt + 273.2) ** 4. - (tcl + 273.2) ** 4.)
rsum = rbare + rclo
C CONVECT
cbare = hc * (ta - tsk) * adu * (1. - facl)
cclo = hc * (ta - tcl ) * acl
csum = cbare + cclo
C CORE
c(0) = h + ere
c(1) = adu * rob * cb
c(2) = 18. - 0.5 * tsk
c(3) = 5.28 * adu * c(2)
c(4) = 0.0208 * c(1)
c(5) = 0.76075 * c(1)
c(6) = c(3) - c(5) - tsk * c(4)
c(7) = - c(0) * c(2) - tsk * c(3) + tsk * c(5)
c(8) = c(6) * c(6) - 4. * c(4) * c(7)
c(9) = 5.28 * adu - c(5) - c(4) * tsk
c(10) = c(9) * c(9) - 4. * c(4) *
+ (c(5) * tsk - c(0) - 5.28 * adu * tsk)
C
if (tsk.eq.36.) tsk=36.01
tcore(7) = c(0) / (5.28 * adu + c(1) * 6.3 / 3600.) + tsk
tcore(3) = c(0) / (5.28 * adu + (c(1) * 6.3 / 3600.) /
+ (1 + 0.5 * (34. -tsk))) + tsk
if (c(10) .lt. 0.) goto 22
tcore(6) = (- c(9) - c(10) ** 0.5) / (2. * c(4))
tcore(1) = (- c(9) + c(10) ** 0.5) / (2. * c(4))
22 if (c(8) .lt. 0.) goto 24
tcore(2) = (- c(6) + abs(c(8)) ** 0.5) / (2. * c(4))
tcore(5) = (- c(6) - abs(c(8)) ** 0.5) / (2. * c(4))
24 tcore(4) = c(0) / (5.28 * adu + c(1) * 1. / 40.) + tsk
C TRANSPARENCE
tbody = 0.1 * tsk + 0.9 * tcore (j)
swm = 304.94 * (tbody - 36.6) * adu / 3600000.
vpts = 6.11 * 10. ** (7.45 * tsk / (235. + tsk))
if (tbody .le. 36.6) swm = 0.
swf = 0.7 * swm
if(sex .eq. 1) sw = swm
if(sex .eq. 2) sw = swf
eswphy = - sw * evap
he = 0.633 * hc / (p * cair)
fec = 1. / (1. + 0.92 * hc * rcl)
eswpot = he * (vpa - vpts) * adu * evap * fec
wetsk = eswphy / eswpot
if (wetsk .gt. 1.) wetsk = 1.
eswdif = eswphy - eswpot
if (eswdif .le. 0.) esw = eswpot
if (eswdif .gt. 0.) esw = eswphy
if (esw .gt. 0.) esw = 0.
C DIFFERENCE
rdsk = 0.79 * 10. ** 7.
rdcl = 0.
ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa-vpts)
C VB
vb1 = 34. - tsk
vb2 = tcore(j) - 36.6
if (vb2 .lt.0.) vb2 = 0.
if (vb1 .lt.0.) vb1 = 0.
vb = (6.3 + 75. * (vb2)) / (1. + 0.5 * vb1)
C BALANCE
enbal = h + ed + ere + esw + csum + rsum + food
C COVER
if (count1 .eq.0) xx = 1.
if (count1 .eq.1) xx = 0.1
if (count1 .eq.2) xx = 0.01
if (count1 .eq.3) xx = 0.001
if (enbal .gt. 0.) tcl = tcl + xx
if (enbal .lt. 0.) tcl = tcl - xx
if ((enbal .le. 0.) .and. (enbal2 .gt. 0.)) goto 30
if ((enbal .ge. 0.) .and. (enbal2 .lt. 0.)) goto 30
enbal2 = enbal
count3 = count3 + 1
C
if (count3 .gt. 200) goto 30
goto 20
30 if ((count1 .eq.0.).or.(count1.eq.1.).or.(count1.eq.2.)) then
count1 = count1 + 1.
enbal2 = 0.
goto 20
end if
C
if (count1 .eq. 3.) then
C
if ((j .eq. 2) .or. (j .eq. 5)) goto 40
if ((j .eq. 6) .or. (j .eq. 1)) goto 50
if (j .eq. 3) goto 60
if (j .eq. 7) goto 70
if (j .eq. 4) goto 80
end if
40 if (c(8) .lt. 0.) goto 90
if ((tcore(j) .ge. 36.6) .and. (tsk .le. 34.050)) goto 80
goto 90
50 if (c(10) .lt. 0. ) goto 90
if ((tcore(j) .ge. 36.6) .and. (tsk .gt. 33.850)) goto 80
goto 90
60 if ((tcore(j) .lt. 36.6) .and. (tsk .le. 34.000)) goto 80
goto 90
70 if ((tcore(j) .lt. 36.6) .and. (tsk .gt. 34.000)) goto 80
goto 90
80 if ((j .ne. 4) .and. (vb .ge. 91.)) goto 90
if ((j. eq. 4) .and. (vb .lt. 89.)) goto 90
if (vb .gt. 90.) vb = 90.
C LOSSES
ws = sw * 3600. * 1000.
if (ws .gt.2000.) ws = 2000.
wd = ed / evap * 3600. * (-1000.)
wr = erel / evap * 3600. * (-1000.)
wsum = ws + wr + wd
goto 100
90 continue
100 return
end
And here is the C# attempt to replicate the upper fortran subroutine:
using System;
public static class GlobalMembers_TEMP
{
//C PROGRAM TEMP
// --------------------------------------------
public static void TEMP(acl, adu, aeff, c, cair, cb, cbare, cclo, count1, csum, di, ed , emcl , emsk , enbal , enbal2 , ere , erel , esw , eswdif , eswphy , eswpot , evap , facl , fcl , fec , feff , food , h , hc , he , ht , htcl , icl , j , mbody , p , po , r1 , r2 , rbare , rcl , rclo , rclo2 , rdcl , rdsk , rob , rsum , sex , sigm , sw , swf , swm , ta , tbody , tcl, tcore , tmrt , tsk , v , vb , vb1 , vb2 , vpa , vpts , wetsk , wd , wr , ws , wsum , xx)
{
float acl;
float adu;
float aeff;
float[] c = new float[11]; // ???
float cair;
float cb;
float cbare;
float cclo;
float csum;
float di;
float ed;
float emcl;
float emsk;
float enbal;
float enbal2;
float ere;
float erel;
float esw;
float eswdif;
float eswphy;
float eswpot;
float evap;
float facl;
float fcl;
float fec;
float feff;
float food;
float h;
float hc;
float he;
float ht;
float htcl;
float icl;
float mbody;
float p;
float po;
float r1;
float r2;
float rbare;
float rcl;
float rclo;
float rclo2;
float rdcl;
float rdsk;
float rob;
float rsum;
float sigm;
float sw;
float swf;
float swm;
float ta;
float tbody;
float tcl;
float[] tcore = new float[7]; // ???
float tmrt;
float tsk;
float v;
float vb;
float vb1;
float vb2;
float vpa;
float vpts;
float wetsk;
float wd;
float wr;
float ws;
float wsum;
float xx;
int count1;
int count3;
int j;
int sex;
wetsk = 0.0;
adu = 0.203 * mbody * *0.425 * ht * *0.725;
hc = 2.67 + (6.5 * v * *0.67);
hc = hc * (p / po) * *0.55;
feff = 0.725;
//C rcl = icl / 6.45
facl = (-2.36 + 173.51 * icl - 100.76 * icl * icl + 19.28 * (icl * *3.0)) / 100.0;
//C
if (facl > 1.0)
{
facl = 1.0;
}
rcl = (icl / 6.45) / facl;
if (icl >= 2.0)
{
y = 1.0;
}
if ((icl > 0.6)) && ((icl < 2.0))
{
y = (ht - 0.2) / ht;
}
if ((icl <= 0.6)) && ((icl > 0.3))
{
y = 0.5;
}
if ((icl <= 0.3)) && ((icl > 0.0))
{
y = 0.1;
}
r2 = adu * (fcl - 1.0 + facl) / (2.0 * 3.14 * ht * y);
r1 = facl * adu / (2.0 * 3.14 * ht * y);
di = r2 - r1;
//C TEMPERATURE
for (90 j = 1, 7)
{
tsk = 34.0;
count1 = 0;
tcl = (ta + tmrt + tsk) / 3.0;
count3 = 1;
enbal2 = 0.0;
g20:
acl = adu * facl + adu * (fcl - 1.0);
rclo2 = emcl * sigm * ((tcl + 273.2) * *4.0 - (tmrt + 273.2) * *4.0) * feff;
htcl = 6.28 * ht * y * di / (rcl * alog(r2 / r1) * acl);
tsk = 1.0 / htcl * (hc * (tcl - ta) + rclo2) + tcl;
//C RADIATION
aeff = adu * feff;
rbare = aeff * (1.0 - facl) * emsk * sigm * ((tmrt + 273.2) * *4.0 - (tsk + 273.2) * *4.0);
rclo = feff * acl * emcl * sigm * ((tmrt + 273.2) * *4.0 - (tcl + 273.2) * *4.0);
rsum = rbare + rclo;
//C CONVECT
cbare = hc * (ta - tsk) * adu * (1.0 - facl);
cclo = hc * (ta - tcl) * acl;
csum = cbare + cclo;
//C CORE
c[0] = h + ere;
c[1] = adu * rob * cb;
c[2] = 18.0 - 0.5 * tsk;
c[3] = 5.28 * adu * c[2];
c[4] = 0.0208 * c[1];
c[5] = 0.76075 * c[1];
c[6] = c[3] - c[5] - tsk * c[4];
c[7] = -c[0] * c[2] - tsk * c[3] + tsk * c[5];
c[8] = c[6] * c[6] - 4.0 * c[4] * c[7];
c[9] = 5.28 * adu - c[5] - c[4] * tsk;
c[10] = c[9] * c[9] - 4.0 * c[4] * (c[5] * tsk - c[0] - 5.28 * adu * tsk);
//C
if (tsk == 36.0)
{
tsk = 36.01;
}
tcore[7] = c[0] / (5.28 * adu + c[1] * 6.3 / 3600.0) + tsk;
tcore[3] = c[0] / (5.28 * adu + (c[1] * 6.3 / 3600.0) / (1 + 0.5 * (34.0 - tsk))) + tsk;
if (c[10] < 0.0)
{
goto g22;
}
tcore[6] = (-c[9] - c[10] * *0.5) / (2.0 * c[4]);
tcore[1] = (-c[9] + c[10] * *0.5) / (2.0 * c[4]);
g22:
if (c[8] < 0.0)
{
goto g24;
}
tcore[2] = (-c[6] + Math.Abs(c[8]) * *0.5) / (2.0 * c[4]);
tcore[5] = (-c[6] - Math.Abs(c[8]) * *0.5) / (2.0 * c[4]);
g24:
tcore[4] = c[0] / (5.28 * adu + c[1] * 1.0 / 40.0) + tsk;
//C TRANSPARENCE
tbody = 0.1 * tsk + 0.9 * tcore[j];
swm = 304.94 * (tbody - 36.6) * adu / 3600000.0;
vpts = 6.11 * 10.0 * *(7.45 * tsk / (235.0 + tsk));
if (tbody <= 36.6)
{
swm = 0.0;
}
swf = 0.7 * swm;
if (sex == 1)
{
sw = swm;
}
if (sex == 2)
{
sw = swf;
}
eswphy = -sw * evap;
he = 0.633 * hc / (p * cair);
fec = 1.0 / (1.0 + 0.92 * hc * rcl);
eswpot = he * (vpa - vpts) * adu * evap * fec;
wetsk = eswphy / eswpot;
if (wetsk > 1.0)
{
wetsk = 1.0;
}
eswdif = eswphy - eswpot;
if (eswdif <= 0.0)
{
esw = eswpot;
}
if (eswdif > 0.0)
{
esw = eswphy;
}
if (esw > 0.0)
{
esw = 0.0;
}
//C DIFFERENCE
rdsk = 0.79 * 10.0 * *7.0;
rdcl = 0.0;
ed = evap / (rdsk + rdcl) * adu * (1 - wetsk) * (vpa - vpts);
//C VB
vb1 = 34.0 - tsk;
vb2 = tcore[j] - 36.6;
if (vb2 < 0.0)
{
vb2 = 0.0;
}
if (vb1 < 0.0)
{
vb1 = 0.0;
}
vb = (6.3 + 75.0 * (vb2)) / (1.0 + 0.5 * vb1);
//C BALANCE
enbal = h + ed + ere + esw + csum + rsum + food;
//C COVER
if (count1 == 0)
{
xx = 1.0;
}
if (count1 == 1)
{
xx = 0.1;
}
if (count1 == 2)
{
xx = 0.01;
}
if (count1 == 3)
{
xx = 0.001;
}
if (enbal > 0.0)
{
tcl = tcl + xx;
}
if (enbal < 0.0)
{
tcl = tcl - xx;
}
if ((enbal <= 0.0)) && ((enbal2 > 0.0))
{
goto g30;
}
if ((enbal >= 0.0)) && ((enbal2 < 0.0))
{
goto g30;
}
enbal2 = enbal;
count3 = count3 + 1;
//C
if (count3 > 200)
{
goto g30;
}
goto g20;
g30:
if ((count1 == 0.0))
{
|| ((count1 == 1.0)) || ((count1 == 2.0))
{
count1 = count1 + 1.0;
enbal2 = 0.0;
goto g20;
}
}
//C
if (count1 == 3.0)
{
//C
if ((j == 2))
{
|| ((j == 5)) goto g40;
}
if ((j == 6))
{
|| ((j == 1)) goto g50;
}
if (j == 3)
{
goto g60;
}
if (j == 7)
{
goto g70;
}
if (j == 4)
{
goto g80;
}
}
g40:
if (c[8] < 0.0)
{
goto g90;
}
if ((tcore[j] >= 36.6)) && ((tsk <= 34.050))
{
goto g80;
}
goto g90;
g50:
if (c[10] < 0.0)
{
goto g90;
}
if ((tcore[j] >= 36.6)) && ((tsk > 33.850))
{
goto g80;
}
goto g90;
g60:
if ((tcore[j] < 36.6)) && ((tsk <= 34.000))
{
goto g80;
}
goto g90;
g70:
if ((tcore[j] < 36.6)) && ((tsk > 34.000))
{
goto g80;
}
goto g90;
g80:
if ((j != 4)) && ((vb >= 91.0))
{
goto g90;
}
if ((j.eq.4)) && ((vb < 89.0))
{
goto g90;
}
if (vb > 90.0)
{
vb = 90.0;
}
//C LOSSES
ws = sw * 3600.0 * 1000.0;
if (ws > 2000.0)
{
ws = 2000.0;
}
wd = ed / evap * 3600.0 * (-1000.0);
wr = erel / evap * 3600.0 * (-1000.0);
wsum = ws + wr + wd;
goto g100;
}
g100:
return;
}
}
You can try to turn this code into a state machine where each state represents a single goto inside the loop.
For that you will need to turn your method into a class, that contains all the parameters and variables as class fields, and has one constructor that initializes appropriate fields and (optionally) runs the "method".
I won't transition your method because it is far too huge as an example, but I will give you the following:
Original not converted method:
public static void Do(Int32 param1, Int32 param2)
{
Int32 loopI;
Int32 outBefore,
outAfter,
outGoto1 = 0,
outGoto2 = 0;
Int32[] outValues = new Int32[7];
Console.WriteLine("METHOD:");
Console.WriteLine("DoBeforeLoop");
outBefore = param1 + param2;
Boolean wasInGoto2 = false;
for (loopI = 0; loopI < 7; loopI++)
{
Console.WriteLine("Iteration {0}", loopI);
Console.WriteLine("FortranLoopMethodState.LoopCycleStart");
outValues[loopI] = loopI;
goto1:
Console.WriteLine("FortranLoopMethodState.Goto1");
outGoto1 = loopI + param1;
if (wasInGoto2)
{
wasInGoto2 = false;
goto end;
}
wasInGoto2 = true;
Console.WriteLine("FortranLoopMethodState.Goto2");
outGoto2 = loopI + param2;
goto goto1;
end:
DoNothing(); // We don't use break, do we?
}
Console.WriteLine("DoAfterLoop");
outAfter = param1 - param2;
Console.WriteLine(outGoto1);
Console.WriteLine(outGoto2);
}
Converted method:
public class ExecuteFortranMethod
{
private enum FortranLoopMethodState
{
LoopCycleStart,
Goto1,
Goto2,
LoopCycleEnded
}
#region Params
private Int32 param1;
private Int32 param2;
#endregion
#region Variables
public Int32 loopI;
public Int32 outBefore,
outAfter,
outGoto1,
outGoto2;
public Int32[] outValues = new Int32[7];
#endregion
#region Constructors
public ExecuteFortranMethod(Int32 param1, Int32 param2)
{
this.param1 = param1;
this.param2 = param2;
this.Invoke();
}
#endregion
#region Methods
private void Invoke()
{
Console.WriteLine("STATE MACHINE CLASS:");
this.DoBeforeLoop();
for (this.loopI = 0; this.loopI < 7; this.loopI++)
{
Console.WriteLine("Iteration {0}", this.loopI);
var state = FortranLoopMethodState.LoopCycleStart;
do
{
state = DoLoop(state);
}
while (state != FortranLoopMethodState.LoopCycleEnded);
}
this.DoAfterLoop();
}
#endregion
#region "Method" body methods
private void DoBeforeLoop()
{
Console.WriteLine("DoBeforeLoop");
this.outBefore = this.param1 + this.param2;
}
private void DoAfterLoop()
{
Console.WriteLine("DoAfterLoop");
this.outAfter = this.param1 - this.param2;
}
Boolean wasInGoto2;
private FortranLoopMethodState DoLoop(FortranLoopMethodState state)
{
switch (state)
{
case FortranLoopMethodState.LoopCycleStart:
{
Console.WriteLine("FortranLoopMethodState.LoopCycleStart");
this.outValues[this.loopI] = this.loopI;
return FortranLoopMethodState.Goto1;
}
case FortranLoopMethodState.Goto1:
{
Console.WriteLine("FortranLoopMethodState.Goto1");
this.outGoto1 = this.loopI + this.param1;
if (this.wasInGoto2)
{
this.wasInGoto2 = false;
return FortranLoopMethodState.LoopCycleEnded;
}
return FortranLoopMethodState.Goto2;
}
case FortranLoopMethodState.Goto2:
{
this.wasInGoto2 = true;
Console.WriteLine("FortranLoopMethodState.Goto2");
this.outGoto2 = this.loopI + this.param2;
return FortranLoopMethodState.Goto1;
}
default:
throw new InvalidOperationException("The state is invalid");
}
}
#endregion
}
Program.cs
Do(10, 20);
Console.WriteLine();
var result = new ExecuteFortranMethod(10, 20);
Console.WriteLine(result.outGoto1);
Console.WriteLine(result.outGoto2);
Console.WriteLine("Press any key");
Console.ReadKey(true);
As you can see the outputs are equivalent. I won't describe exactly how you can transfer the actual method, because it is a tedious (but not unreal) task with no real shortcuts and most of the ideas will be clear when you read even this tiny example.
P.S.1: While there are no real shortucts (except of course of writing some small tool that can generate such state machine classes for the given code), you may simplify the manual job with a bit of regular expressions search and replace (Ctrl+F). For example, replacing pattern goto(\d+) with case State.Goto$1 { will replace all gotos with switch case stubs.
P.S.2: If there are far too many switch cases(gotos) you may want to replace switch with some Dictionary lookup.
P.S.3: And as many have already pointed it, I'd still recommend you to try to understand the original code flow and to rewrite it from scratch.
A goto inside the loop means two things:
stop the current execution of the loop (that's like using continue)
skip everything before the goto label (that's like using an if)
Instead of if-statements you could theoretically use a big switch statement without breaks on each case (fall through mode), so instead of doing a goto you can just set the switch value (create a variable) to the correct position and then call continue.
But that would be the same logic and lead to the same problems that you have when using gotos. It is not understandable, debuggable, maintainable for someone who didn't write the code. After 3-4 months it is even hard for the same person.
As a first step you should try to take each block and identify what exactly it does and if possible extract it to a method/function with a good name.
When your finished you hopefully have a huge goto mess with some function calls in it. Try to reduce the mess with if statements. g70 looks like a probable candidate because it conditionaly performs the g80 stuff or skips it and continues at g90, but haven't looked in detail at it.
Once you have it down to that level, you can also make execution graphs, one row (maybe in a spreadsheet) for each goto label and just write down which functions then get called until it reaches another goto.
Basic for a good refactoring is a good understanding of the problem, so maybe interviewing the person who wrote the pascal code to explain what it does can help you a lot.
Would be fun to see what you made out of the code once it's done and what it really does!

Infinite looping

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.

Low pass filter with directsound implementation issue

Currently I am developing a c# low pass filter in real time using directsound API. The problem that I've encountered is that various implementations of low pass filters seem not to work with my echo implementation. At the begining of the filtering I have an array of bytes (read) that is read from the capturing buffer. The values of this array are between 0 and 255.
When I subject the array to low-pass filtering algorithm I obtain values that fall between 0 and 1 and as an effect the play array is silent (zeros only). I attach the relevant code.
I imagine that that this approach is wrong and probably the input data should look different as the low pass algorithm seems to kill it completely. Any ideas? Thanks in advance.
Updated relevant code after KillaKem's comments:
//buffer format
var format = new WaveFormat
{
SamplesPerSecond = 44100,
BitsPerSample = 16,
Channels = 2,
FormatTag = WaveFormatTag.Pcm
};
//reading the buffer
byte[] read = (byte[])_dwCapBuffer.Read(offset, typeof(byte), LockFlag.None, _dwOutputBufferSize);
byte[] play = new byte [read.Length];
byte[] readL= new byte [read.Length/2];
byte[] readR= new byte [read.Length/2];
byte[] playL = new byte[read.Length / 2];
byte[] playR = new byte[read.Length / 2];
float[] readLfloat = new float[read.Length / 4];
float[] readRfloat = new float[read.Length / 4];
float[] playLfloat = new float[read.Length / 4];
float[] playRfloat = new float[read.Length / 4];
//dividing into channels and casting to float
for(int i = 0; i<read.Length; i=i+1)
{
if (i % 4 == 0)
{
readL[(int)i / 2] = read[i];
}
if(i%4==1)
{
readL[(int)i/2]=read[i];
readLfloat[(int)i / 4] = (((short)(read[i-1] << 8 | read[i])) / 32768f);
}
if (i % 4 == 2)
{
readR[(int)i / 2] = read[i];
}
if (i % 4 == 3)
{
readR[(int)i / 2] = read[i];
readRfloat[(int)i / 4] = (((short)(read[i - 1] << 8 | read[i])) / 32768f);
}
}
//filter coefficients
float frequency = 1000f;
float sampleRate = (float)_dwCapBuffer.Format.SamplesPerSecond;
float resonance = 0.5f;
float c = 1.0f / (float)Math.Tan(Math.PI * frequency / sampleRate);
float a0 = 1.0f / (1.0f + resonance * c + c * c);
float a1 = 2f * a0;
float a2 = a0;
float b1 = 2.0f * (1.0f - c * c) * a0;
float b2 = (1.0f - resonance * c + c * c) * a0;
//filtering
for(int i = 0; i < readLfloat.Length; i++)
{
float readCurrSample = readLfloat[i];
float playCurrSample = playLfloat[i];
float filtered=readCurrSample;
float readOneSample;
float readTwoSample;
float playOneSample;
float playTwoSample;
if (i ==0)
{
filtered = ((float)a0 * readCurrSample) + ((float)a1 * savelastRead) + ((float)a2 * saveprelastRead) - ((float)b1 * savelastPlay) - ((float)b2 * saveprelastPlay);
}
else if (i==1)
{
readOneSample = readLfloat[i-1];
playOneSample = playLfloat[i-1];
filtered = ((float)a0 * readCurrSample) + ((float)a1 * readOneSample) + ((float)a2 * savelastRead) - ((float)b1 * playOneSample) - ((float)b2 * savelastPlay);
}
else
{
readOneSample = readLfloat[i - 1];
playOneSample = playLfloat[i - 1];
readTwoSample = readLfloat[i - 2];
playTwoSample = playLfloat[i - 2];
filtered = ((float)a0 * readCurrSample) + ((float)a1 * readOneSample) + ((float)a2 * readTwoSample) - ((float)b1 * playOneSample) - ((float)b2 * playTwoSample);
}
if (i == readL.Length - 4)
{
saveprelastPlay = playCurrSample;
saveprelastRead = readCurrSample;
}
if (i == readL.Length-2)
{
savelastPlay = playCurrSample;
savelastRead = readCurrSample;
}
if (filtered > 1 || filtered < -1)
{
int x = 0;
}
playLfloat[i] = filtered;
}
playRfloat = playLfloat; //ignoring Right channel operations
//Recasting to bytes array
for (int i = 0; i < read.Length; i = i + 1)
{
if (i % 4 == 1)
{
byte[] bytes;
bytes = BitConverter.GetBytes((short)(playLfloat[(int)(i-1)/4] * 32768f));
read[i] = bytes[0];
read[i - 1] = bytes[1];
}
if (i % 4 == 3)
{
byte[] bytes;
bytes = BitConverter.GetBytes((short)(playRfloat[(int)(i - 1) / 4] * 32768f));
read[i] = bytes[0];
read[i - 1] = bytes[1];
}
}

GammaLn NameSpace In C#

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;
}

Categories