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