Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * rational fractions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <oskar@scara.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2019 Trent Piepho <tpiepho@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * helper functions when coping with rational numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/rational.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/minmax.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * calculate best rational approximation for a given fraction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * taking into account restricted register size, e.g. to find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * appropriate values for a pll with 5 bit denominator and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * 8 bit numerator register fields, trying to set up with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * frequency ratio of 3.1415, one would say:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * rational_best_approximation(31415, 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * you may look at given_numerator as a fixed point number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * with the fractional part size described in given_denominator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * for theoretical background, see:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * https://en.wikipedia.org/wiki/Continued_fraction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) void rational_best_approximation(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	unsigned long given_numerator, unsigned long given_denominator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	unsigned long max_numerator, unsigned long max_denominator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	unsigned long *best_numerator, unsigned long *best_denominator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	/* n/d is the starting rational, which is continually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	 * decreased each iteration using the Euclidean algorithm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	 * dp is the value of d from the prior iteration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	 * n2/d2, n1/d1, and n0/d0 are our successively more accurate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	 * approximations of the rational.  They are, respectively,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	 * the current, previous, and two prior iterations of it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	 * a is current term of the continued fraction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	unsigned long n, d, n0, d0, n1, d1, n2, d2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	n = given_numerator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	d = given_denominator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	n0 = d1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	n1 = d0 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		unsigned long dp, a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		if (d == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		/* Find next term in continued fraction, 'a', via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		 * Euclidean algorithm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		dp = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		a = n / d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		d = n % d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		n = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		/* Calculate the current rational approximation (aka
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		 * convergent), n2/d2, using the term just found and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		 * the two prior approximations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		n2 = n0 + a * n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		d2 = d0 + a * d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		/* If the current convergent exceeds the maxes, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		 * return either the previous convergent or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		 * largest semi-convergent, the final term of which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		 * found below as 't'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		if ((n2 > max_numerator) || (d2 > max_denominator)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			unsigned long t = ULONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			if (d1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				t = (max_denominator - d0) / d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			if (n1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 				t = min(t, (max_numerator - n0) / n1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			/* This tests if the semi-convergent is closer than the previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			 * convergent.  If d1 is zero there is no previous convergent as this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			 * is the 1st iteration, so always choose the semi-convergent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			if (!d1 || 2u * t > a || (2u * t == a && d0 * dp > d1 * d)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				n1 = n0 + t * n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 				d1 = d0 + t * d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		n0 = n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		n1 = n2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		d0 = d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		d1 = d2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	*best_numerator = n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	*best_denominator = d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) EXPORT_SYMBOL(rational_best_approximation);