Simplistic implementation of rational numbers.
 public static Rational ContinuedFraction(double x)
 {
     Debug.Assert(0 <= x && x < 1.0);
     int scale = 1;
     while (x < 0.5)
     {
         x *= 2.0;
         scale *= 2;
     }
     var a = new List<int>();
     while (x > 1e-6 && a.Count < 10)
     {
         var r = 1.0 / x;
         int a1 = (int)r;
         x = r - a1;
         a.Add(a1);
     }
     Debug.Print("cfrac [{0}]", string.Join(", ", a));
     var rat = new Rational(0, 1);
     for (int i = a.Count-1; i >= 0; --i)
     {
         rat = a[i] + rat;
         rat = rat.Reciprocal();
     }
     rat = rat / scale;
     Debug.Print("crat: {0}", rat);
     return rat;
 }
        /// <summary>
        /// Determine whether <paramref name="instr"/> is a match for 
        /// the pattern that is a constant division
        /// </summary>
        /// <remarks>
        /// The pattern is:
        /// <code>
        /// hi:lo = r * const
        /// hi = slice(hi:lo) (alias)
        /// hi = hi >> shift  (optional)
        /// </code>
        /// This transformation must be carried out before value propagation
        /// pushes the shift inside other operations.
        /// </remarks>
        /// <param name="instr"></param>
        /// <returns></returns>
        public bool Match(Instruction instr)
        {
            Assignment ass;
            SequenceStorage dst;
            BinaryExpression bin;
            Constant cRight;

            // Look for hi:lo = a * C
            if (!instr.As(out ass) ||
                !ass.Dst.Storage.As(out dst) ||
                !ass.Src.As(out bin) ||
                !(bin.Operator is IMulOperator) ||
                !bin.Right.As(out cRight) ||
                ass.Dst.DataType.Size <= bin.Left.DataType.Size)
            {
                return false;
            }

            this.idOrig = ass.Dst;
            this.idDst = FindAlias(ass.Dst, dst.Head);
            if (idDst == null)
                return false;

            var best = FindBestRational(cRight.ToUInt32());

            // There may be a subsequent SAR / SHR to increase 
            // the divisor.

            var idSlice = idDst;
            Constant rShift = null;
            if (idSlice != null)
            {
                rShift = FindShiftUse(idSlice);
                if (rShift != null)
                {
                    best = best / (1 << rShift.ToInt32());
                }
            }
            this.bestRational = best;

            this.dividend = bin.Left;
            return true;
        }