Blame view

lib/rational.c 1.49 KB
8759ef32d   Oskar Schirmer   lib: isolate rati...
1
2
3
4
5
6
7
8
9
  /*
   * rational fractions
   *
   * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <os@emlix.com>
   *
   * helper functions when coping with rational numbers
   */
  
  #include <linux/rational.h>
7ee3aebe3   Sascha Hauer   lib/rational.c ne...
10
  #include <linux/module.h>
8759ef32d   Oskar Schirmer   lib: isolate rati...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  
  /*
   * calculate best rational approximation for a given fraction
   * taking into account restricted register size, e.g. to find
   * appropriate values for a pll with 5 bit denominator and
   * 8 bit numerator register fields, trying to set up with a
   * frequency ratio of 3.1415, one would say:
   *
   * rational_best_approximation(31415, 10000,
   *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
   *
   * you may look at given_numerator as a fixed point number,
   * with the fractional part size described in given_denominator.
   *
   * for theoretical background, see:
   * http://en.wikipedia.org/wiki/Continued_fraction
   */
  
  void rational_best_approximation(
  	unsigned long given_numerator, unsigned long given_denominator,
  	unsigned long max_numerator, unsigned long max_denominator,
  	unsigned long *best_numerator, unsigned long *best_denominator)
  {
  	unsigned long n, d, n0, d0, n1, d1;
  	n = given_numerator;
  	d = given_denominator;
  	n0 = d1 = 0;
  	n1 = d0 = 1;
  	for (;;) {
  		unsigned long t, a;
  		if ((n1 > max_numerator) || (d1 > max_denominator)) {
  			n1 = n0;
  			d1 = d0;
  			break;
  		}
  		if (d == 0)
  			break;
  		t = d;
  		a = n / d;
  		d = n % d;
  		n = t;
  		t = n0 + a * n1;
  		n0 = n1;
  		n1 = t;
  		t = d0 + a * d1;
  		d0 = d1;
  		d1 = t;
  	}
  	*best_numerator = n1;
  	*best_denominator = d1;
  }
  
  EXPORT_SYMBOL(rational_best_approximation);