ON 20090526@8:03:33 AM at page: On a web page you were interested in at: http://piclist.com/techref/microchip/math/vector/index.htm#39959.335787037 Nikolai Golovchenko[NG--944] Code:
There are several approximate methods for finding magnitude. They vary in their complexity and accuracy. Here is a list of some options: Method 1. Accurate up to -0..+8%. Requires a multiply by a constant. int magnitude_Robertson(int x, int y) { int mx; int mn; x = abs(x); y = abs(y); mx = max(x, y); mn = min(x, y); return mx + mn*k; } The method is apparently due to: Robertson, G.H., "A Fast Amplitude Approximation for Quadrature Pairs", Bell Sys. Tech. J., Vol. 50, Oct. 1971, pp.2849-2852. The constant k is chosen to minimize error in one of different ways (average error, absolute error, peak-to-peak error, standard deviation, etc) and efficient to compute the multiply. A few examples: 1/2, 3/8, 1/4: suggested by Robertson sqrt(2)-1 ~= 106/256: minimizes p-p error (also, zero error at multiples of 45 deg) Method 2. Accurate to 2.8%. Requires three constant multiplies. int magnitude_Levitt(int x, int y) { int mx; int mn; x = abs(x); y = abs(y); mx = max(x, y); mn = min(x, y); if(mx >= 3*mn) return mx + mn/8; else return mx*7/8 + mn/2; } See B.K Levitt, G.A. Morris, "An Improved Digital Algorithm for Fast Amplitude Approximations of Quadrature Pairs", DSN Progress Report 42-40, May and June 1977, pp 97-101. <a href="http://tmo.jpl.nasa.gov/progress_report2/42-40/40L.PDF">http://tmo.jpl.nasa.gov/progress_report2/42-40/40L.PDF</a> Method 3. Accurate up to -1.5%...+0%. Requires a divide, multiply, and a constant multiply. int magnitude3(int x, int y) { int mx; int mn; x = abs(x); y = abs(y); mx = max(x, y); mn = min(x, y); if(mx == 0) return mx; return mx + mn*mn/mx*k; } The constant k is chosen similarly to method 1. For example, k=sqrt(2)-1~=106/256 again minimizes the p-p error. The method is due to Nikolai Golovchenko. :) Method 4. Accurate up to -0.5%..+0%. Requires a divide, multiply, and two constant multiplies. This is a piecewise refinement of method 3. Vector (x,y) is assumed to be rotated to the range of 0 to 45 deg (i.e. x=mx and y=mn as in examples above) b = y/x if b <= 0.5 b += b * 0.14 // ~5/32 else b += (1-b) * 0.14 r = x + y * b * 106/256 Method 5: Theoretically arbitrary accuracy. Requires a divide and two multiplies. r = x + y * lookup(y/x) lookup() - a function that represents a table with linear interpolation.ON 20090526@9:48:06 AM at page: On a web page you were interested in at: http://piclist.com/techref/microchip/math/vector/index.htm#39959.4084027778 Nikolai Golovchenko[NG--944] Code:
Method 2B. Accurate to -1.2%..+0.8%. Requires up to four constant multiplies. This method refines Levitt/Morris method. int magnitude2B(int x, int y) { int mx; int mn; x = abs(x); y = abs(y); mx = max(x, y); mn = min(x, y); if(mx >= 3*mn) return mx + mn/8; else if (mx >= 5/4*mn) return mx*7/8 + mn/2; else return mx*3/4 + mn*21/32; }