1 #!/usr/bin/env python2 2 3 from math import ceil, floor 4 import sys 5 6 def is_integer(x): 7 target = round(x) * 1000 8 #print x, target - 100, floor(x * 1000), target + 100 9 return target - 100 < floor(x * 1000) < target + 100 10 11 def getscale(x): 12 scale = getscale_part(x) 13 if is_integer(scale): 14 return scale 15 return scale * getscale(scale) 16 17 def getscale_part(x): 18 part = x - int(x) 19 if not part: 20 return 1 21 elif part > 0.5: 22 return 1 / (1 - part) 23 else: 24 return 1 / part 25 26 def get_divider_operands(frequency, source_frequency): 27 ratio = float(frequency) / source_frequency 28 scale = getscale(ratio) 29 return scale * ratio, scale 30 31 def reduce_divider_operands(m, n, m_limit, n_limit): 32 while m > m_limit and n > n_limit and m > 1 and n > 1: 33 m /= 2 34 n /= 2 35 return m, n 36 37 def show(s, m, n, f_label="f"): 38 print "m =", m 39 print "n =", n 40 print "%s' =" % f_label, s * m / n 41 print "%s' ~=" % f_label, s * round(m) / round(n) 42 43 if len(sys.argv) < 4: 44 f, s = map(float, sys.argv[1:3]) 45 m, n = get_divider_operands(f, s) 46 m, n = reduce_divider_operands(m, n, 0x200, 0x100000) 47 show(s, m, n) 48 49 else: 50 f, s, i_min, i_max = map(float, sys.argv[1:5]) 51 52 # Constraints: 53 # 54 # i_min < s * m' / di < i_max 55 # i_min / s < m' / di < i_max / s 56 # 57 # f = s * m' / (di * do) 58 # f = (s * m' / di) / do 59 # f * do = s * m' / di 60 # 61 # i_min < f * do < i_max 62 # i_min / f < do < i_max / f 63 # 64 # f = s * m / n 65 # 66 # s * m' / (di * do) = s * m / n 67 # m' / (di * do) = m / n 68 # m' = (m / n) * (di * do) 69 # m' / di = (m / n) * do 70 71 do_min = ceil(i_min / f) 72 do_max = floor(i_max / f) 73 74 do = do_min 75 76 print do_min, "<= do <=", do_max 77 78 while do <= do_max: 79 do0 = int(do ** 0.5) 80 do1 = int(do / do0) 81 if do0 * do1 == int(do): 82 i = do * f 83 m, n = get_divider_operands(i, s) 84 m, n = reduce_divider_operands(m, n, 0x3f, 0x3f) 85 if m <= 0x3f and n <= 0x3f: 86 show(s, m, n, "i") 87 print "do =", do 88 print "do0 =", do0 89 print "do1 =", do1 90 print "f' =", s * m / (n * do) 91 print "m =", round(m) 92 print "n =", round(n) 93 print "f' ~=", s * round(m) / (round(n) * round(do)) 94 break 95 else: 96 print "Ignored: m =", m, "n =", n, "do0 =", do0, "do1 =", do1 97 do += 1 98 99 # vim: tabstop=4 expandtab shiftwidth=4