Elliptic curve factorisng in c# 4.0 - c#

I am trying to implement Elliptic curve factorisation in c# 4.
I have a few problems though.
Firstly, my version appears to be invredibly slow. Factorising 89041 * 93563 has taken about 5 minutes on a 2GHZ dual core machine and required computing 273!P.
Also I haven't been able to find a profiler for c# 4 to determine what is actually taking the time however I suspect that the O(log(N)) recursive calls in CalcNP are probably not very fast when N >> 100!.
Any help on making this run faster?
Code:
using System;
using System.Collections.Generic;
using bint = System.Numerics.BigInteger;
namespace ECM
{
public class Program
{
static Tuple<bint, bint>[] pow2store; //caches the values of 2^n * P
static bint Factor;
static bint max2powstored = 0;
static int maxexp = 0;
public static void Main(string[] args)
{
pow2store = new Tuple<bint, bint>[100000];
bint n = 89041 * (bint)93563;
//curve params from wiki article
bint x = 1;
bint y = 1;
bint a = 5;
bint b = (y * y - x * x * x - a * x) % n;
bool ftest = false;
var P = new Tuple<bint, bint>(x, y);
pow2store[0] = P;
var twop = twoP(b, P, n, out ftest);
pow2store[1] = twop;
int factsteps = 1;
bint factorial = 1;
while (!ftest)
{
factorial *= ++factsteps;
Console.WriteLine("calculating {0}! p", factsteps);
CalcNP(factorial, b, n, out ftest);
}
Console.WriteLine("{0} = {1} * {2}", n, Factor, n / Factor);
Console.ReadKey(true);
}
static Tuple<bint, bint> CalcNP(bint calc, bint b, bint n, out bool res)
{
int powguess = (int)Math.Floor(bint.Log(calc, 2));
powguess = Math.Min(powguess, maxexp);
bint max2pow = bint.Pow(2, (int)powguess);
while (max2pow * 2 <= calc)
{
max2pow *= 2;
powguess++;
if (max2pow > max2powstored)
{
maxexp++;
max2powstored = max2pow;
pow2store[powguess] = twoP(b, pow2store[powguess - 1], n, out res);
if (res)
{
return pow2store[powguess];
}
}
}
calc -= max2pow;
if (calc > 1)
{
var Q = CalcNP(calc, b, n, out res);
if (res)
{
return new Tuple<bint, bint>(0, 0);
}
return ECadd(pow2store[powguess], Q, n, out res);
}
else
{
res = false;
return pow2store[powguess];
}
}
static Tuple<bint, bint> twoP(bint b, Tuple<bint, bint> P, bint n, out bool Factor)
{
bint stop = (3 * P.Item1 * P.Item1 - b) % n;
bint sbottom = (2 * P.Item2) % n;
bint inv = ModInv(sbottom, n, out Factor);
if (Factor)
{
return new Tuple<bint, bint>(0, 0);
}
bint s = (stop * inv) % n;
bint xR = (s * s - 2 * P.Item1) % n;
bint yR = (s * (P.Item1-xR)-P.Item2) % n;
return new Tuple<bint, bint>(xR, yR);
}
static Tuple<bint, bint> ECadd(Tuple<bint, bint> P, Tuple<bint, bint> Q, bint n, out bool Factor)
{
bint stop = P.Item2 - Q.Item2 % n;
bint sbottom = (P.Item1 - Q.Item1) % n;
bint inv = ModInv(sbottom, n, out Factor);
if (Factor)
{
return new Tuple<bint, bint>(0, 0);
}
bint s = (stop * inv) % n;
bint xR = (s * s - P.Item1 - Q.Item1) % n;
bint yR = (s * (xR-P.Item1) - P.Item2) % n;
return new Tuple<bint, bint>(xR, yR);
}
static bint ModInv(bint a, bint m, out bool notcoprime)
{
bint[] arr = ExtGCD(a, m);
if (!bint.Abs(arr[2]).IsOne)
{
Console.WriteLine("found factor when inverting {0} mod {1}", (a + m) % m, m);
Factor = arr[2];
notcoprime = true;
return 0;
}
else
{
notcoprime = false;
return arr[0];
}
}
//extended euclidean
static bint[] ExtGCD(bint a, bint b)
{
bint x = 0;
bint y = 1;
bint u = 1;
bint v = 0;
while (b != 0)
{
bint buffer = b;
bint q = a / b;
b = a % b;
a = buffer;
buffer = x;
x = u - q * x;
u = buffer;
buffer = y;
y = v - q * y;
v = buffer;
}
return new bint[] { u, v, a };
}
}
}

You do realize that this kind of factorization was designed to be computationally infeasible?
Looking at your code though, there's nothing in there that's exceptionally slow, except maybe the BigInteger type itself. However, if you need arbitrary sized integers that's the price you pay.
If this is just a mathematical exercise I'd consider myself done unless you wanna explore a different factorization algorithm for which there exist no algorithm that terminate with an optimal solution in polynomial time.
I should add that only given that the problem was designed to be hard to compute is there no feasible way to do factorization. I was automatically thinking cracking encryption which might have been confusing to some people.

Related

How do you leave roots in surd form in c#?

Example a: √12 =2√3
Example b: √16 = 4
I am trying to get both.
Whilst I can of course use Math.Sqrt(4) to achieve outcome b, I've no idea how to achieve a, or further how to get both to work simultaneously which is the goal. How do I achieve this type of simplification in C#?
I have tried several libraries including MathNet, Symbolics and NCalc with no success.
This post may have solved it in c++, although I do not know for sure. My attempts at converting that solution to even see if it worked were very much a failure:
var outside_root = 1;
var inside_root = 800;
var d = 2;
while (d * d <= inside_root)
if (inside_root % (d * d) == 0) //# inside_root evenly divisible by d * d
{
inside_root = inside_root / (d * d);
outside_root = (outside_root * d);
}
while (d * d > inside_root) {
d = (d + 1);}
Thank you for any help
The given C++ can be translated into C# without a lot of changes. Also a couple of modifications can be made to the original algorithm to reduce number of multiplications and increase overall performance:
static (int, int) Sqrt2(int n)
{
int m = 1, d = 2;
int dSquared;
while ((dSquared = d * d) <= n)
{
while ((n % dSquared) == 0)
{
n /= dSquared;
m *= d;
}
d++;
}
return (m, n);
}
static void Main(string[] args)
{
Console.WriteLine(Sqrt2(12)); // prints (2, 3)
Console.WriteLine(Sqrt2(16)); // prints (4, 1)
Console.WriteLine(Sqrt2(13)); // prints (1, 13)
}
This could be one of the solution
I think this is efficient. I used it in my calculator app
I did that using java. Hope this will help
static void surd_form(long a) {
long i = 2;
long sq = 1;
long k = 4;
long p = 1;
while (k <= a) {
if (a % i == 0) {
if (a % k == 0) {
a /= k;
sq *= i;
} else {
a /= i;
p *= i;
}
} else {
i += 1;
}
k = i * i;
}
System.out.println(sq + "" + "√" + (a * p));
}

Laplace Transform And Getting The Frequent Value For Gyro

I'm getting x,y,z values from gyro-sensor. Each variable is being sent 10 values per second. In 3 seconds I have;
x=[30values]
y=[30values]
z=[30values]
Some of the values are too different from the others cause of noise. With laplace transform I need to get the most frequent value from my array.
I need to filter the array with Laplace Transform equation. I need to build the equation in C#. How can I implement the array with the equation?
Since this kind of filter (Laplace) is very specialized to certain area of Engineering and needs a person who has good understanding on both the programming language (in this case is C#) and the filter itself, I would recommend you to use such source, rather than code the filter by yourself.
Here is the snippet of the source code:
class Laplace
{
const int DefaultStehfest = 14;
public delegate double FunctionDelegate(double t);
static double[] V; // Stehfest coefficients
static double ln2; // log of 2
public static void InitStehfest(int N)
{
ln2 = Math.Log(2.0);
int N2 = N / 2;
int NV = 2 * N2;
V = new double[NV];
int sign = 1;
if ((N2 % 2) != 0)
sign = -1;
for (int i = 0; i < NV; i++)
{
int kmin = (i + 2) / 2;
int kmax = i + 1;
if (kmax > N2)
kmax = N2;
V[i] = 0;
sign = -sign;
for (int k = kmin; k <= kmax; k++)
{
V[i] = V[i] + (Math.Pow(k, N2) / Factorial(k)) * (Factorial(2 * k)
/ Factorial(2 * k - i - 1)) / Factorial(N2 - k)
/ Factorial(k - 1) / Factorial(i + 1 - k);
}
V[i] = sign * V[i];
}
}
public static double InverseTransform(FunctionDelegate f, double t)
{
double ln2t = ln2 / t;
double x = 0;
double y = 0;
for (int i = 0; i < V.Length; i++)
{
x += ln2t;
y += V[i] * f(x);
}
return ln2t * y;
}
public static double Factorial(int N)
{
double x = 1;
if (N > 1)
{
for (int i = 2; i <= N; i++)
x = i * x;
}
return x;
}
}
coded by Mr. Walt Fair Jr. in CodeProject.

BigInteger/BigRational problems with converting to double and back

Maybe I didn't understood how to use those two types: BigInteger/BigRational, but generally speaking I want to implement those two equations:
This is my data: n=235, K = 40 and this small p (which actually is called rho) is 5. In the beginning the problem was with the Power function: the results were very very very big - so that is why I used the BigInteger library. But then I realize that there will be a division made and the result will be a number of type double - so I changed to BigRational library.
Here is my code:
static void Main(string[] args)
{
var k = 40;
var n = 235;
var p = 5;
// the P(n) equation
BigRational pnNumerator = BigRational.Pow(p, n);
BigRational pnDenominator = BigRational.Pow(k, (n - k)) * Factorial(k);
// the P(0) equation
//---the right side of "+" sign in Denominator
BigRational pk = BigRational.Pow(p, k);
BigRational factorialK = Factorial(k);
BigRational lastPart = (BigRational.Subtract(1, (double)BigRational.Divide(p, k)));
BigRational factorialAndLastPart = BigRational.Multiply(factorialK, lastPart);
BigRational fullRightSide = BigRational.Divide(pk, factorialAndLastPart);
//---the left side of "+" sign in Denominator
BigRational series = Series(k, p, n);
BigRational p0Denominator = series + fullRightSide;
BigRational p0Result = BigRational.Divide(1, p0Denominator);
BigRational pNResult = BigRational.Divide((pnNumerator * p0Result), pnDenominator);
Console.WriteLine(pNResult);
Console.ReadKey();
}
static BigRational Series(int k, int p, int n)
{
BigRational series = new BigRational(0.0);
var fin = k - 1;
for (int i = 0; i < fin; i++)
{
var power = BigRational.Pow(p, i);
var factorialN = Factorial(n);
var sum = BigRational.Divide(power, factorialN);
series += sum;
}
return series;
}
static BigRational Factorial(int k)
{
if (k <= 1)
return 1;
else return BigRational.Multiply(k, Factorial(k - 1));
}
The main problem is that it does not return any "normal" value like for example 0.3 or 0.03. The result which is printed to the console is a very long number (like 1200 digits in it)...
Can someone please take a look at my code and help me fix the problem and be able to solve this equations by the code. Thank you
Console.WriteLine(pNResult); calls BigRational.ToString() under-the-hood, which prints the number in the form numerator/denominator.
It's easy to miss the / in the output given how large the numerator and denominator both are in this case.
BigRational supports conversions to decimal and to double. The result is too small to fit in a decimal in this case though. Converting to a double, gives the result 7.89682541396914E-177.
If you need better precision, you'll need a custom conversion to a decimal-format string, like the one in this Stackoverflow answer.
Using that custom conversion routine to get the result to 1000 decimal places -
Console.WriteLine(pNResult.ToDecimalString(1000));
- gives the result as:
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078968254139691306770128897137459492828971170349380336740935269651539684650525033676003134593283361305530675112470528408219177025044254116462798561450442318290046626248451723040397770263675109107145461310779641705093156106311143727608208629473359566457461384474633112850335950017209558136575135801388668687571284492241030561019606955986265585636660304889792027894460104216176719717671500843399685686146432982358441225578366059001576682388503227237202077881334695352338638383337717103303153521108812750644260562351186866587629456292506971252525125976755540274041651740194108430555751648707933592643410475214924394223640168857340953563111097979394441303100701008120008166339365089771585037880235325673143152814510586536335380671360865230428857049658368242543653234599817430185879648427434216378356518036776477170130227628307039
To check that your calculation code is operating correctly, you can add unit-tests for the different functions (Factorial, Series and the computation of P itself).
An approach that is practical here is to calculate the results by hand for certain small values of k, n and p and check that your functions compute the same results.
If you're using Visual Studio, you can use this MSDN page as a starting point for creating a unit-test project. Note that the functions under test must be visible to the unit-test project, and your unit-test project will need to have a reference added to your existing project where you're doing the computation, as explained in the link.
Starting with Factorial, which is the easiest to check, you could add a test like this:
[TestClass]
public class UnitTestComputation
{
[TestMethod]
public void TestFactorial()
{
Assert.AreEqual(1, Program.Factorial(0));
Assert.AreEqual(1, Program.Factorial(1));
Assert.AreEqual(2, Program.Factorial(2));
Assert.AreEqual(6, Program.Factorial(3));
Assert.AreEqual(24, Program.Factorial(4));
}
}
The code in your question passes that test.
You can then add a test method for your Series function:
[TestMethod]
public void TestSeries()
{
int k = 1;
int p = 1;
BigRational expected = 1;
Assert.AreEqual(expected, Program.Series(k, p));
k = 2;
p = 1;
expected += 1;
Assert.AreEqual(expected, Program.Series(k, p));
k = 3;
p = 1;
expected += (BigRational)1 / (BigRational)2;
Assert.AreEqual(expected, Program.Series(k, p));
k = 1;
p = 2;
expected = 1;
Assert.AreEqual(expected, Program.Series(k, p));
k = 2;
p = 2;
expected += 2;
Assert.AreEqual(expected, Program.Series(k, p));
}
This showed up some problems in your code:
n shouldn't actually be a parameter to this function, because in this context n isn't the parameter to function P, but actually just the "index-of-summation". n's local value in this function is represented by your i variable.
This then means that your Factorial(n) call needs to change to Factorial(i)
The loop is also off-by-one, because the Sigma notation for the summation is inclusive of the number at the top of the Sigma, so you should have <= fin (or you could also have written this simply as < k).
This is the updated Series function:
// CHANGED: Removed n as parameter (n just the index of summation here)
public static BigRational Series(int k, int p)
{
BigRational series = new BigRational(0.0);
var fin = k - 1;
// CHANGED: Should be <= fin (i.e. <= k-1, or < k) because it's inclusive counting
for (int i = 0; i <= fin; i++)
{
var power = BigRational.Pow(p, i);
// CHANGED: was Factorial(n), should be factorial of n value in this part of the sequence being summed.
var factorialN = Factorial(i);
var sum = BigRational.Divide(power, factorialN);
series += sum;
}
return series;
}
To test the P(n) calculation you can move that out into its own function to test (I've called it ComputeP here):
[TestMethod]
public void TestP()
{
int n = 1;
int k = 2;
int p = 1;
// P(0) = 1 / (2 + 1/(2*(1 - 1/2))) = 1/3
// P(1) = (1/(1/2 * 2)) * P(0) = P(0) = 1/3
BigRational expected = 1;
expected /= 3;
Assert.AreEqual(expected, Program.ComputeP(k, n, p));
n = 2;
k = 2;
p = 1;
// P(2) = (1/(1*2)) * P(0) = 1/6
expected = 1;
expected /= 6;
Assert.AreEqual(expected, Program.ComputeP(k, n, p));
}
This showed up a problem with calculating P(n) - you had a cast to double in there which shouldn't have been present (the result is inaccurate then - you need to keep all the intermediate results in BigRational). There's no need for the cast, so just removing it fixes this problem.
Here is the updated ComputeP function:
public static BigRational ComputeP(int k, int n, int p)
{
// the P(n) equation
BigRational pnNumerator = BigRational.Pow(p, n);
BigRational pnDenominator = BigRational.Pow(k, (n - k)) * Factorial(k);
// the P(0) equation
//---the right side of "+" sign in Denominator
BigRational pk = BigRational.Pow(p, k);
BigRational factorialK = Factorial(k);
// CHANGED: Don't cast to double here (loses precision)
BigRational lastPart = (BigRational.Subtract(1, BigRational.Divide(p, k)));
BigRational factorialAndLastPart = BigRational.Multiply(factorialK, lastPart);
BigRational fullRightSide = BigRational.Divide(pk, factorialAndLastPart);
//---the left side of "+" sign in Denominator
BigRational series = Series(k, p);
BigRational p0Denominator = series + fullRightSide;
BigRational p0Result = BigRational.Divide(1, p0Denominator);
BigRational pNResult = BigRational.Divide((pnNumerator * p0Result), pnDenominator);
return pNResult;
}
For avoidance of confusion, here is the whole updated calculation program:
using System;
using System.Numerics;
using System.Text;
using Numerics;
public class Program
{
public static BigRational ComputeP(int k, int n, int p)
{
// the P(n) equation
BigRational pnNumerator = BigRational.Pow(p, n);
BigRational pnDenominator = BigRational.Pow(k, (n - k)) * Factorial(k);
// the P(0) equation
//---the right side of "+" sign in Denominator
BigRational pk = BigRational.Pow(p, k);
BigRational factorialK = Factorial(k);
// CHANGED: Don't cast to double here (loses precision)
BigRational lastPart = (BigRational.Subtract(1, BigRational.Divide(p, k)));
BigRational factorialAndLastPart = BigRational.Multiply(factorialK, lastPart);
BigRational fullRightSide = BigRational.Divide(pk, factorialAndLastPart);
//---the left side of "+" sign in Denominator
BigRational series = Series(k, p);
BigRational p0Denominator = series + fullRightSide;
BigRational p0Result = BigRational.Divide(1, p0Denominator);
BigRational pNResult = BigRational.Divide((pnNumerator * p0Result), pnDenominator);
return pNResult;
}
// CHANGED: Removed n as parameter (n just the index of summation here)
public static BigRational Series(int k, int p)
{
BigRational series = new BigRational(0.0);
var fin = k - 1;
// CHANGED: Should be <= fin (i.e. <= k-1, or < k) because it's inclusive counting
for (int i = 0; i <= fin; i++)
{
var power = BigRational.Pow(p, i);
// CHANGED: was Factorial(n), should be factorial of n value in this part of the sequence being summed.
var factorialN = Factorial(i);
var sum = BigRational.Divide(power, factorialN);
series += sum;
}
return series;
}
public static BigRational Factorial(int k)
{
if (k <= 1)
return 1;
else return BigRational.Multiply(k, Factorial(k - 1));
}
static void Main(string[] args)
{
var k = 40;
var n = 235;
var p = 5;
var result = ComputeP(k, n, p);
Console.WriteLine(result.ToDecimalString(1000));
Console.ReadKey();
}
}
// From https://stackoverflow.com/a/10359412/4486839
public static class BigRationalExtensions
{
public static string ToDecimalString(this BigRational r, int precision)
{
var fraction = r.GetFractionPart();
// Case where the rational number is a whole number
if (fraction.Numerator == 0 && fraction.Denominator == 1)
{
return r.GetWholePart() + ".0";
}
var adjustedNumerator = (fraction.Numerator
* BigInteger.Pow(10, precision));
var decimalPlaces = adjustedNumerator / fraction.Denominator;
// Case where precision wasn't large enough.
if (decimalPlaces == 0)
{
return "0.0";
}
// Give it the capacity for around what we should need for
// the whole part and total precision
// (this is kinda sloppy, but does the trick)
var sb = new StringBuilder(precision + r.ToString().Length);
bool noMoreTrailingZeros = false;
for (int i = precision; i > 0; i--)
{
if (!noMoreTrailingZeros)
{
if ((decimalPlaces % 10) == 0)
{
decimalPlaces = decimalPlaces / 10;
continue;
}
noMoreTrailingZeros = true;
}
// Add the right most decimal to the string
sb.Insert(0, decimalPlaces % 10);
decimalPlaces = decimalPlaces / 10;
}
// Insert the whole part and decimal
sb.Insert(0, ".");
sb.Insert(0, r.GetWholePart());
return sb.ToString();
}
}
And here is the whole unit-test program:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Numerics;
[TestClass]
public class UnitTestComputation
{
[TestMethod]
public void TestFactorial()
{
Assert.AreEqual(1, Program.Factorial(0));
Assert.AreEqual(1, Program.Factorial(1));
Assert.AreEqual(2, Program.Factorial(2));
Assert.AreEqual(6, Program.Factorial(3));
Assert.AreEqual(24, Program.Factorial(4));
}
[TestMethod]
public void TestSeries()
{
int k = 1;
int p = 1;
BigRational expected = 1;
Assert.AreEqual(expected, Program.Series(k, p));
k = 2;
p = 1;
expected += 1;
Assert.AreEqual(expected, Program.Series(k, p));
k = 3;
p = 1;
expected += (BigRational)1 / (BigRational)2;
Assert.AreEqual(expected, Program.Series(k, p));
k = 1;
p = 2;
expected = 1;
Assert.AreEqual(expected, Program.Series(k, p));
k = 2;
p = 2;
expected += 2;
Assert.AreEqual(expected, Program.Series(k, p));
}
[TestMethod]
public void TestP()
{
int n = 1;
int k = 2;
int p = 1;
// P(0) = 1 / (2 + 1/(2*(1 - 1/2))) = 1/3
// P(1) = (1/(1/2 * 2)) * P(0) = P(0) = 1/3
BigRational expected = 1;
expected /= 3;
Assert.AreEqual(expected, Program.ComputeP(k, n, p));
n = 2;
k = 2;
p = 1;
// P(2) = (1/(1*2)) * P(0) = 1/6
expected = 1;
expected /= 6;
Assert.AreEqual(expected, Program.ComputeP(k, n, p));
}
}
Incidentally, the P(n) result with the updated program for your input values for n, p and k is now:
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000593109980769066916025972569398424267669807629726200017375290861590898269902277869938365969961320969473356001666906480007119114830921839913623591124192047955091318951831902550404167336054683697071654765071519020060437129398945035521954738463786221029427589397688847246112810536958194364039693387170592425527136243952416704526069736811587380688876091926255908361275575249492845970903676492429684929779402600032481018886875698972533534890841796034626337674846620462046294537488580901129338625628349474358946962065227890599744775562637784553656488649841148591533557896418988044457914999854241038974478576578909626765823565817758792682480009619613438867365912697996527957775248350987801430141776875171808382272960426476953742528769626555642957093028553993908356226007570404005591174451216846471710162760343
NOTE: You should add to the unit-tests with more results you've checked by hand, and also check any of my working here in interpreting the algebra as code to ensure this is correct.

BetaInv function in SQL Server

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.

How to compute ifft from fft?

I've done a fft to get fundamental frequency in real time and to implement high and low pass filters.
Now I want to be able to record to a .wav file after I apply a filter.
First I'll have to invert the fft and that is my question.
What are the steps to do this?
I use the FFT defined in this project.
Here is the code for it:
using System;
using System.Collections.Generic;
using System.Text;
namespace SoundLog
{
public class FourierTransform
{
static private int n, nu;
static private int BitReverse(int j)
{
int j2;
int j1 = j;
int k = 0;
for (int i = 1; i <= nu; i++)
{
j2 = j1 / 2;
k = 2 * k + j1 - 2 * j2;
j1 = j2;
}
return k;
}
static public double[] FFT(ref double[] x)
{
// Assume n is a power of 2
n = x.Length;
nu = (int)(Math.Log(n) / Math.Log(2));
int n2 = n / 2;
int nu1 = nu - 1;
double[] xre = new double[n];
double[] xim = new double[n];
double[] magnitude = new double[n2];
double[] decibel = new double[n2];
double tr, ti, p, arg, c, s;
for (int i = 0; i < n; i++)
{
xre[i] = x[i];
xim[i] = 0.0f;
}
int k = 0;
for (int l = 1; l <= nu; l++)
{
while (k < n)
{
for (int i = 1; i <= n2; i++)
{
p = BitReverse(k >> nu1);
arg = 2 * (double)Math.PI * p / n;
c = (double)Math.Cos(arg);
s = (double)Math.Sin(arg);
tr = xre[k + n2] * c + xim[k + n2] * s;
ti = xim[k + n2] * c - xre[k + n2] * s;
xre[k + n2] = xre[k] - tr;
xim[k + n2] = xim[k] - ti;
xre[k] += tr;
xim[k] += ti;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 = n2 / 2;
}
k = 0;
int r;
while (k < n)
{
r = BitReverse(k);
if (r > k)
{
tr = xre[k];
ti = xim[k];
xre[k] = xre[r];
xim[k] = xim[r];
xre[r] = tr;
xim[r] = ti;
}
k++;
}
for (int i = 0; i < n / 2; i++)
//magnitude[i] = (float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i])));
decibel[i] = 10.0 * Math.Log10((float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i]))));
//return magnitude;
return decibel;
}
}
}
There are so many really good fft implementations around such as FFTW that I highly recommend using one. They come with ifft as well. Yours, as implemented, will be excruciatingly slow.

Categories