rational.c 1.6 KB

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