using System;
using System.Data.Sql;
using System.Data.SqlTypes;
public class CPulley
{
    [SqlFunction]
    public static double PulleyDistance(
	double Pulley1Diameter,
	double Pulley2Diameter,
	double BeltLength)
    {
		double length = 0;
		double a = 2.0;
		double b = BeltLength - 1.57 * (Pulley1Diameter + Pulley2Diameter);
		double c = System.Math.Pow(Pulley1Diameter - Pulley2Diameter, 2.0);
		// if this is not positive no chance the pulleys will fit
		double b1 = Math.Pow(b, 2.0) - (4 * a * c);
		if(b1 > 0)
		{
			length = (b + Math.Sqrt(b1)) / (2 * a);
			// check that pulleys fit
			if (length < ((Pulley1Diameter + Pulley2Diameter) / 2))
			{
				// return 0 if pulleys don't fit
				length = 0;
			}
		}
		// one decimal point is enough
		return System.Math.Round(length, 1);
    }

	[SqlFunction]
	public static SqlDecimal PulleyDistanceD(
		SqlDecimal Pulley1Diameter, 
		SqlDecimal Pulley2Diameter,
		SqlDecimal BeltLength)
	{
		SqlDecimal length = 0M;
		SqlDecimal a = 2.0M;
		SqlDecimal b = BeltLength - 1.57M * (Pulley1Diameter + Pulley2Diameter);
		SqlDecimal c = SqlDecimal.Power(Pulley1Diameter - Pulley2Diameter,
										2);

		// if this is not positive no chance the pulleys will fit
		SqlDecimal b1 = SqlDecimal.Power(b,
										 2) - (4M * a * c);

		if (b1.ToDouble()  > (2 * Double.MinValue) )
		{
			bool run = true;
			SqlDecimal s1 = 0;
			try
			{
				s1 = new SqlDecimal(Math.Sqrt(b1.ToDouble() - Double.MinValue));
			}
			catch
			{
				run = false;
			}	
			if (run)
			{
				SqlDecimal testS1 = s1;
				SqlDecimal diff = SqlDecimal.Abs(b1 - (s1 * s1));
				SqlDecimal dmin = 1000 * SqlDecimal.MinValue;

				for (SqlDecimal test = testS1 - dmin; test <= (testS1 + dmin); test += dmin)
				{
					SqlDecimal d = SqlDecimal.Abs(b1 - (test * test));

					if (d < diff)
					{
						s1 = test;
						diff = d;
					}
				}

				length = (b + s1) / (2M * a);

				// check that pulleys fit
				if (length < ((Pulley1Diameter + Pulley2Diameter) / 2M))
				{
					// return 0 if pulleys don't fit
					length = 0;
				}
			}
		}

		// one SqlDecimal point is enough
		return SqlDecimal.AdjustScale(length,
									  2,
									  true);
	}


	[SqlFunction]
	public static double BeltLength(
		double Pulley1Diameter, 
		double Pulley2Diameter, 
		double PulleyDistance)
	{
		double length = (2 * PulleyDistance) + 
		(1.57 * (Pulley1Diameter + Pulley2Diameter)) + 
		((System.Math.Pow((Pulley1Diameter - Pulley2Diameter), 2.0) / (4 * PulleyDistance)));
		return length;
	}
};
#if false
class app
{
	static void Main()
	{
		double P1 = 20;
		double P2 = 10;
		double L = 120;
		Console.WriteLine(L);
		double C = CPulley.PulleyDistance(P1, P2, L);
		Console.WriteLine(C);
		Console.WriteLine(CPulley.BeltLength(P1, P2, C));
	}
}

#endif
