<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Marius Bancila's Blog &#187; numerics</title>
	<atom:link href="http://mariusbancila.ro/blog/tag/numerics/feed/" rel="self" type="application/rss+xml" />
	<link>http://mariusbancila.ro/blog</link>
	<description>Sharing my opinions and ideas!</description>
	<lastBuildDate>Mon, 14 Nov 2011 07:19:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>BigInteger Is Back</title>
		<link>http://mariusbancila.ro/blog/2009/03/03/biginteger-is-back/</link>
		<comments>http://mariusbancila.ro/blog/2009/03/03/biginteger-is-back/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 05:30:03 +0000</pubDate>
		<dc:creator>Marius Bancila</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[CTPs & Betas]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[integer]]></category>
		<category><![CDATA[numerics]]></category>
		<category><![CDATA[VS2010]]></category>

		<guid isPermaLink="false">http://mariusbancila.ro/blog/?p=211</guid>
		<description><![CDATA[One of the new features in .NET 4.0 is the BigInteger class. This was suppose to be part of 3.5 framework, but after the CTP it was gone. Now it&#8217;s back. This big integer is a really large integer representation. However, I was not able to find the precision documented anywhere. The class is available [...]]]></description>
			<content:encoded><![CDATA[<p>One of the new features in .NET 4.0 is the BigInteger class. This was suppose to be part of 3.5 framework, but after the CTP it was gone. Now it&#8217;s back. This big integer is a really large integer representation. However, I was not able to find the precision documented anywhere.</p>
<p>The class is available in the System.Numerics namespace and provides overloaded operators, parsing methods and other utility features for bit integer numbers.</p>
<p>Not very long ago, on <a href="http://www.codexpert.ro" target="_blank">codexpert.ro</a> we launched a contest for finding the biggest pair of <a href="http://en.wikipedia.org/wiki/Amicable_number" target="_blank">amicable numbers</a>. One of the members (crystyce) that submited a solution found this big pair (2724918040393706557785752240819405848576, 2724918040396184856306258038787235905536) with a <a href="http://www.codexpert.ro/forum/viewtopic.php?f=18&#038;t=958&#038;start=15#p6241" target="_blank">C++ implementation</a> using a 3rd party BigInt class. I decided to put that in C# 4.0 and use BigInteger. Maybe you can find things to optimize in the below code, but that&#8217;s not the point here. I&#8217;m showing you this code just to get a feeling of BitInteger.</p>
<pre class="prettyprint">
using System.Numerics;

namespace cs_test
{
   static class Amicable
   {
      public static BigInteger Pow2(BigInteger exp)
      {
         BigInteger res = 1;

         for (BigInteger i = 0; i < exp; i++)
            res *= 2;

         return res;
      }

      public static BigInteger ExpMod(BigInteger value, BigInteger exp, BigInteger mod)
      {
         BigInteger ullResult = 1;
         BigInteger ullValue = value;

         while (exp > 0)
         {
            if (exp % 2 != 0)
            { // odd
               ullResult *= ullValue;
               ullResult %= mod;
            }

            ullValue *= ullValue;
            ullValue %= mod;
            exp /= 2;
         }

         return (ullResult);
      }

      static public bool IsMillerRabinPrime(BigInteger prime)
      {
         // randomWitness = witness that the "prime" is NOT composite
         // 1 < randomWitness < prime-1
         long totalWitness = 15;
         BigInteger [] randomWitness = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 51001, 351011};
         BigInteger primeMinusOne = prime - 1;
         BigInteger oddMultiplier;
         long bitLength;
         long i, j;
         BigInteger result;
         // find oddMultiplier, defined as "prime - 1 = (2^B) * M"
         // get bitLength (B) and find the oddMultiplier (M)

         // init value multiplier
         oddMultiplier = primeMinusOne;

         bitLength = 0; // reset
         while(oddMultiplier % 2 == 0)
         {
            oddMultiplier /= 2;
            bitLength++;
         }
         for(i = 0; i < totalWitness; i++)
         {
            if (randomWitness[i] == prime)
               return true;

            // init value of result = (randomWitness ^ oddMultiplier) mod prime
            result = ExpMod(randomWitness[i], oddMultiplier, prime);

            // is y = 1 ?
            if(result == 1)
               continue; // maybe prime

            // is y = prime-1 ?
            if(result == primeMinusOne)
               continue; // maybe prime

            // loop to get AT LEAST one "result = primeMinusOne"
            for(j = 1; j <= bitLength; j++)
            {
               // square of result
               result = ExpMod(result, 2, prime);

               // is result = primeMinusOne ?
               if(result == primeMinusOne)
                  break; // maybe prime
            }

            if(result != primeMinusOne)
               return false; // COMPOSITE
         }

         // it may be pseudoprime/prime
         return true;
      }

   }

   class Program
   {
      const int STARTM = 1;
      const int STOPM = 100;
      const int STOPN = 30;

      static void Main(string[] args)
      {
         DateTime start = DateTime.Now;

         for (BigInteger m = STARTM ; m <= STOPM ; m++)
         {
            for (BigInteger n = m+1 ; n <= m+STOPN ; n++)
            {
               BigInteger p = Amicable.Pow2(n) + Amicable.Pow2(m) - 1;
               if (!Amicable.IsMillerRabinPrime(p)) continue;

               BigInteger q = Amicable.Pow2(2 * n - m) + Amicable.Pow2(n) - 1;
               if (!Amicable.IsMillerRabinPrime(q)) continue;

               BigInteger r = Amicable.Pow2(3 * n - m) +
                              Amicable.Pow2(n + m) +
                              Amicable.Pow2(2 * n + 1) - 1;
               if (!Amicable.IsMillerRabinPrime(r)) continue;

               BigInteger f1 = Amicable.Pow2(n) * p * q;
               BigInteger f2 = Amicable.Pow2(n) * r;

               DateTime end = DateTime.Now;
               Console.WriteLine(
                  "{2} ... {0}, {1}",
                  f1,
                  f2,
                  (end - start).Milliseconds / 1000.0);
            }
         }
      }
   }
}
</pre>
<pre class="prettyprint">
0.017 ... 220, 284
0.021 ... 2172649216, 2181168896
0.028 ... 17296, 18416
0.040 ... 9363584, 9437056
0.138 ... 2.7249180403937065577857522408E+39, 2.7249180403961848563062580388E+39
</pre>
<p>As you can see, it was very fast finding the same big pair. Well it was at least on my 2 core machine.</p>
<p>The only thing I don't understand about the implementation is the presence of some helper functions in the BigInteger class.</p>
<pre class="prettyprint">
public static BigInteger Abs(BigInteger value);
public static BigInteger Add(BigInteger left, BigInteger right);
public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right);
public static BigInteger Divide(BigInteger dividend, BigInteger divisor);
public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder);
public static double Log(BigInteger value);
public static double Log(BigInteger value, double baseValue);
public static double Log10(BigInteger value);
public static BigInteger Max(BigInteger left, BigInteger right);
public static BigInteger Min(BigInteger left, BigInteger right);
public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus);
public static BigInteger Multiply(BigInteger left, BigInteger right);
public static BigInteger Negate(BigInteger value);
public static BigInteger Pow(BigInteger value, int exponent);
public static BigInteger Remainder(BigInteger dividend, BigInteger divisor);
public static BigInteger Subtract(BigInteger left, BigInteger right);
</pre>
<p>That belongs to <b>System.Math</b>, or maybe to a <b>System.Numerics.Math</b> class. They are all helper functions, not specific to the implementation of the big integer; and the implementation does not depend on the existing of these functions. So they are clearly utility functions. They should go somewhere else. I have submitted this as feedback to Microsoft Connect. If you agree with it, vote for it <a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=421758">here</a>. Of course, if you have arguments for the current implementation, you can vote against it too.</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://mariusbancila.ro/blog/2009/03/03/biginteger-is-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

