From owner-freebsd-numerics@FreeBSD.ORG Mon Aug 13 16:57:50 2012 Return-Path: Delivered-To: freebsd-numerics@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 53C0C1065674 for ; Mon, 13 Aug 2012 16:57:50 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from fallbackmx10.syd.optusnet.com.au (fallbackmx10.syd.optusnet.com.au [211.29.132.251]) by mx1.freebsd.org (Postfix) with ESMTP id 131D68FC19 for ; Mon, 13 Aug 2012 16:57:48 +0000 (UTC) Received: from mail01.syd.optusnet.com.au (mail01.syd.optusnet.com.au [211.29.132.182]) by fallbackmx10.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id q7DGve2X017635 for ; Tue, 14 Aug 2012 02:57:40 +1000 Received: from c122-106-171-246.carlnfd1.nsw.optusnet.com.au (c122-106-171-246.carlnfd1.nsw.optusnet.com.au [122.106.171.246]) by mail01.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id q7DGvRjD001896 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 14 Aug 2012 02:57:32 +1000 Date: Tue, 14 Aug 2012 02:57:27 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Stephen Montgomery-Smith In-Reply-To: <5027F07E.9060409@missouri.edu> Message-ID: <20120814003614.H3692@besplex.bde.org> References: <5017111E.6060003@missouri.edu> <501C361D.4010807@missouri.edu> <20120804165555.X1231@besplex.bde.org> <501D51D7.1020101@missouri.edu> <20120805030609.R3101@besplex.bde.org> <501D9C36.2040207@missouri.edu> <20120805175106.X3574@besplex.bde.org> <501EC015.3000808@missouri.edu> <20120805191954.GA50379@troutmask.apl.washington.edu> <20120807205725.GA10572@server.rulingia.com> <20120809025220.N4114@besplex.bde.org> <5027F07E.9060409@missouri.edu> MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="0-1116022701-1344877047=:3692" Cc: freebsd-numerics@FreeBSD.org Subject: Re: Complex arg-trig functions X-BeenThere: freebsd-numerics@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Discussions of high quality implementation of libm functions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Aug 2012 16:57:50 -0000 This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --0-1116022701-1344877047=:3692 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed On Sun, 12 Aug 2012, Stephen Montgomery-Smith wrote: > Having brooded over the code for too many weeks, I now think I have finished > my complex arg-trig functions. I have also written versions for float and > long. So I am ready to have the code reviewed. > > http://people.freebsd.org/~stephen/ I finally tested a version of this. I only did simple comparisons (float vs double and double vs long double). The results look promising after fixing a few bugs: % amd64 float prec, on 2**12 * 2**12 args: % rcacos:max_er = 0x58460841 2.7585, avg_er = 0.317, #>=1:0.5 = 29084:255712 % rcacosh:max_er = 0x5e1e45e6 2.9412, avg_er = 0.262, #>=1:0.5 = 85868:3413684 % rcasin:max_er = 0x631b8183 3.0971, avg_er = 0.209, #>=1:0.5 = 38388:382508 % rcasinh:max_er = 0x5e1e45e6 2.9412, avg_er = 0.262, #>=1:0.5 = 85868:3413684 % rcatan:max_er = 0x51d7c47a 2.5576, avg_er = 0.290, #>=1:0.5 = 52984:318084 % rcatanh:max_er = 0x3693fccd4f 436.6246, avg_er = 0.223, #>=1:0.5 = 213124:1438280 % rclog: max_er = 0x26dfae4d 1.2148, avg_er = 0.247, #>=1:0.5 = 184:92244 % icacos:max_er = 0x5e1e45e6 2.9412, avg_er = 0.262, #>=1:0.5 = 85868:3413684 % icacosh:max_er = 0x3690000000 436.5000, avg_er = 0.317, #>=1:0.5 = 29104:255732 % icasin:max_er = 0x5e1e45e6 2.9412, avg_er = 0.262, #>=1:0.5 = 85868:3413684 % icasinh:max_er = 0x631b8183 3.0971, avg_er = 0.209, #>=1:0.5 = 38388:382508 % icatan:max_er = 0x3693fccd4f 436.6246, avg_er = 0.223, #>=1:0.5 = 213124:1438280 % icatanh:max_er = 0x51d7c47a 2.5576, avg_er = 0.290, #>=1:0.5 = 52984:318084 % iclog: max_er = 0x1fc2b4f5 0.9925, avg_er = 0.302, #>=1:0.5 = 0:349830 % % amd64 double prec, on 2**12 x 2**12 args: % rcacos:max_er = 0x1b5a 3.4189, avg_er = 0.228, #>=1:0.5 = 2394:125988 % rcacosh:max_er = 0xf7d 1.9360, avg_er = 0.257, #>=1:0.5 = 612:2741860 % rcasin:max_er = 0x15c5 2.7212, avg_er = 0.113, #>=1:0.5 = 33296:99152 % rcasinh:max_er = 0xf7d 1.9360, avg_er = 0.257, #>=1:0.5 = 612:2741796 % rcatan:max_er = 0x8000000000000000 4503599627370496.0000, avg_er = 268435456.212, #>=1:0.5 = 4681:81365 % rcatanh:max_er = 0x8000000000000000 4503599627370496.0000, avg_er = 268435456.047, #>=1:0.5 = 428997:691341 % rclog: max_er = 0x704 0.8770, avg_er = 0.250, #>=1:0.5 = 0:20152 % icacos:max_er = 0xf7d 1.9360, avg_er = 0.257, #>=1:0.5 = 612:2741860 % icacosh:max_er = 0x1b5a 3.4189, avg_er = 0.228, #>=1:0.5 = 2394:125988 % icasin:max_er = 0xf7d 1.9360, avg_er = 0.257, #>=1:0.5 = 612:2741796 % icasinh:max_er = 0x15c5 2.7212, avg_er = 0.113, #>=1:0.5 = 33296:99152 % icatan:max_er = 0x8000000000000000 4503599627370496.0000, avg_er = 268435456.047, #>=1:0.5 = 428997:691341 % icatanh:max_er = 0x8000000000000000 4503599627370496.0000, avg_er = 268435456.212, #>=1:0.5 = 4681:81365 % iclog: max_er = 0x6f4 0.8691, avg_er = 0.213, #>=1:0.5 = 0:181032 rfoo is the real part of foo, etc. 2**12 x 2**12 args is not enough. Some bugs showed up only with slightly more args, but after fixing some bugs the behaviour doesn't seem to depend so much on the number. The error of 436.6246 upls has been turning up a lot. It was for a bug in my test program for a result of 0 when the correctly rounded result is the smallest denormal, but I thought I fixed it. The error of 0x8000000000000000 for double precision *catan* is a sign mismatch. % i386 float prec, on 2**12 x 2**12 args: % rcacos:max_er = 0x42cd19c6 2.0875, avg_er = 0.314, #>=1:0.5 = 3854:215116 % rcacosh:max_er = 0x3170e232 1.5450, avg_er = 0.254, #>=1:0.5 = 23008:3245028 % rcasin:max_er = 0x55adc0df 2.6775, avg_er = 0.208, #>=1:0.5 = 34304:353980 % rcasinh:max_er = 0x3170e232 1.5450, avg_er = 0.254, #>=1:0.5 = 23008:3245028 % rcatan:max_er = 0x3c4078ec 1.8829, avg_er = 0.284, #>=1:0.5 = 13260:190836 % rcatanh:max_er = 0x3693fccd4f 436.6246, avg_er = 0.186, #>=1:0.5 = 4796:421616 % rclog: max_er = 0x25830853 1.1722, avg_er = 0.246, #>=1:0.5 = 120:24892 % icacos:max_er = 0x3170e232 1.5450, avg_er = 0.254, #>=1:0.5 = 23008:3245028 % icacosh:max_er = 0x3690000000 436.5000, avg_er = 0.315, #>=1:0.5 = 3874:215136 % icasin:max_er = 0x3170e232 1.5450, avg_er = 0.254, #>=1:0.5 = 23008:3245028 % icasinh:max_er = 0x55adc0df 2.6775, avg_er = 0.208, #>=1:0.5 = 34304:353980 % icatan:max_er = 0x3693fccd4f 436.6246, avg_er = 0.186, #>=1:0.5 = 4796:421616 % icatanh:max_er = 0x3c4078ec 1.8829, avg_er = 0.284, #>=1:0.5 = 13260:190836 % iclog: max_er = 0x1fc2b4f5 0.9925, avg_er = 0.302, #>=1:0.5 = 0:338712 % % i386 double prec, on 2**12 x 2**12 args: % rcacos:max_er = 0x11e8 2.2383, avg_er = 0.165, #>=1:0.5 = 248:111850 % rcacosh:max_er = 0xb02 1.3760, avg_er = 0.256, #>=1:0.5 = 104:2715312 % rcasin:max_er = 0x13ce 2.4756, avg_er = 0.112, #>=1:0.5 = 5616:95060 % rcasinh:max_er = 0xb02 1.3760, avg_er = 0.256, #>=1:0.5 = 104:2715312 % rcatan:max_er = 0x9ed 1.2407, avg_er = 0.015, #>=1:0.5 = 4084:48920 % rcatanh:max_er = 0xb17 1.3862, avg_er = 0.014, #>=1:0.5 = 56:77456 % rclog: max_er = 0x704 0.8770, avg_er = 0.250, #>=1:0.5 = 0:20112 % icacos:max_er = 0xb02 1.3760, avg_er = 0.256, #>=1:0.5 = 104:2715312 % icacosh:max_er = 0x11e8 2.2383, avg_er = 0.165, #>=1:0.5 = 248:111850 % icasin:max_er = 0xb02 1.3760, avg_er = 0.256, #>=1:0.5 = 104:2715312 % icasinh:max_er = 0x13ce 2.4756, avg_er = 0.112, #>=1:0.5 = 5616:95060 % icatan:max_er = 0xb17 1.3862, avg_er = 0.014, #>=1:0.5 = 56:77456 % icatanh:max_er = 0x9ed 1.2407, avg_er = 0.015, #>=1:0.5 = 4084:48920 % iclog: max_er = 0x6f4 0.8691, avg_er = 0.213, #>=1:0.5 = 0:181032 Note that i386 doesn't have the sign errors. However, i386 with -O0 has the sign errors for at least float precision in the same places that amd64 with -O has them for double precision. > The long versions require a logl and a log1pl, which I faked using mpfr. > > The float versions are more complicated, because FLT_EPSILON is too close to > the 4th root of FLT_MIN. It is simpler to make the float versions wrappers > for the double versions. But I wrote the float versions anyway, just in case > some purist insists that the wrapper approach is morally wrong. There are negative reasons to have the float versions unless they are not wrappers. The reasons to have non-wrappers are to test the algorithm and run faster. Fixes needed for the above test results: @ diff -c2 catrig.c~ catrig.c @ *** catrig.c~ Sun Aug 12 17:29:18 2012 @ --- catrig.c Mon Aug 13 12:07:09 2012 @ *************** @ *** 265,269 **** @ return; @ } @ ! if (y < MIN_4TH_ROOT) { @ /* @ * Avoid a possible underflow caused by y/A. For casinh this @ --- 265,269 ---- @ return; @ } @ ! if (!ISNAN(x) && y < MIN_4TH_ROOT) { @ /* @ * Avoid a possible underflow caused by y/A. For casinh this This stops the result for NaN x depending on the size of y relative to MIN_4TH_ROOT. MIN_4TH_ROOT varies with the precision, but the result shouldn't vary with the precision. The result should probably be the original NaN x quieted (unless y is also NaN). This happens naturally if you do a computation with x (except -x). However, symmetry often requires forcing or flipping signs, and we force or flip the sign even for NaNs. This change gives consistent signs for NaN results, by taking the same path in all precisions. @ *************** @ *** 408,416 **** @ @ if (ISFINITE(bx) && ISFINITE(by) && (x > RECIP_SQRT_EPSILON_100 || y > RECIP_SQRT_EPSILON_100)) { @ ! if (huge+x+y>one) { /* raise inexact flag */ @ ! w = clog_for_large_values(z) + M_LN2; Addition clobbers the sign of -0 in the imaginary part in some cases. I think it should clobber it in all cases, since it does for non-complex doubles (-0.0 + +0.0 is +0.0). Clobbering was observed in the following cases: - on i386 (-march=athlon64) with -O0, presumably because the addition to the imaginary part was not optimized away then - on amd64 with -O0 and -O, presumably because: - same as i386 for -O0 - with -O (no -march), float complex and double complex are represented as a vector in an SSE2 register, and it is natural to add both the components of the vector, and this may be optimal for at least float complex with the default -march. I didn't check what happens for double complex. @ if (sy == 0) @ ! return (cpack(cimag(w), -creal(w))); @ ! return (cpack(-cimag(w), creal(w))); The sign of creal(cacos()) is always 1, but this makes it +- the sign of atan2(x, y). @ } @ } @ --- 408,420 ---- @ @ if (ISFINITE(bx) && ISFINITE(by) && (x > RECIP_SQRT_EPSILON_100 || y > RECIP_SQRT_EPSILON_100)) { @ ! /* XXX following can also raise overflow */ Just note this error. @ ! if (huge+x+y>one) { /* raise inexact */ Start removing ' flag'. @ ! w = clog_for_large_values(z); @ ! /* Can't add M_LN2 to w since it should clobber -0*I. */ @ ! rx = fabs(cimag(w)); @ ! ry = creal(w) + M_LN2; @ if (sy == 0) @ ! ry = -ry; @ ! return (cpack(rx, ry)); @ } @ } Fix the above bugs. @ *************** @ *** 482,486 **** @ * but this case should happen extremely rarely. @ */ @ ! if (ay > 0.5*DBL_MAX) @ return (cpack(log(hypot(x / M_E, y / M_E)) + 1, atan2(y, x))); @ @ --- 486,490 ---- @ * but this case should happen extremely rarely. @ */ @ ! if (ax > 0.5*DBL_MAX) @ return (cpack(log(hypot(x / M_E, y / M_E)) + 1, atan2(y, x))); @ The smallest of ax and ay must be compared. I think I broke this in an early version of clog(). Replacing the whole function by clog() made little difference once this was fixed. @ diff -c2 catrigf.c~ catrigf.c @ *** catrigf.c~ Sun Aug 12 17:00:52 2012 @ --- catrigf.c Mon Aug 13 14:14:42 2012 @ *************** @ *** 138,142 **** @ return; @ } @ ! if (y < MIN_4TH_ROOT) { @ *B_is_usable = 0; @ if ((int)y==0) /* raise inexact flag */ @ --- 138,142 ---- @ return; @ } @ ! if (!isnan(x) && y < MIN_4TH_ROOT) { @ *B_is_usable = 0; @ if ((int)y==0) /* raise inexact flag */ @ *************** @ *** 233,240 **** @ if (isfinite(x) && isfinite(y) && (x > RECIP_SQRT_EPSILON_100 || y > RECIP_SQRT_EPSILON_100)) { @ if (huge+x+y>one) { /* raise inexact flag */ @ ! w = clog_for_large_values(z) + M_LN2; @ if (sy == 0) @ ! return (cpackf(cimagf(w), -crealf(w))); @ ! return (cpackf(-cimagf(w), crealf(w))); @ } @ } @ --- 233,242 ---- @ if (isfinite(x) && isfinite(y) && (x > RECIP_SQRT_EPSILON_100 || y > RECIP_SQRT_EPSILON_100)) { @ if (huge+x+y>one) { /* raise inexact flag */ @ ! w = clog_for_large_values(z); @ ! rx = fabsf(cimagf(w)); @ ! ry = crealf(w) + M_LN2; @ if (sy == 0) @ ! ry = -ry; @ ! return (cpackf(rx, ry)); @ } @ } @ *************** @ *** 290,294 **** @ } @ @ ! if (ay > 0.5*FLT_MAX) @ return (cpackf(logf(hypotf(x / M_E, y / M_E)) + 1, atan2f(y, x))); @ @ --- 292,296 ---- @ } @ @ ! if (ax > 0.5*FLT_MAX) @ return (cpackf(logf(hypotf(x / M_E, y / M_E)) + 1, atan2f(y, x))); @ @ diff -c2 catrigl.c~ catrigl.c @ *** catrigl.c~ Sun Aug 12 06:54:46 2012 @ --- catrigl.c Mon Aug 13 12:08:21 2012 @ *************** @ *** 119,123 **** @ return; @ } @ ! if (y < MIN_4TH_ROOT) { @ *B_is_usable = 0; @ if ((int)y==0) /* raise inexact flag */ @ --- 119,123 ---- @ return; @ } @ ! if (!isnan(x) && y < MIN_4TH_ROOT) { @ *B_is_usable = 0; @ if ((int)y==0) /* raise inexact flag */ @ *************** @ *** 207,214 **** @ if (isfinite(x) && isfinite(y) && (x > RECIP_SQRT_EPSILON_100 || y > RECIP_SQRT_EPSILON_100)) { @ if (huge+x+y>one) { /* raise inexact flag */ @ ! w = clog_for_large_values(z) + L_LN2; @ if (sy == 0) @ ! return (cpackl(cimagl(w), -creall(w))); @ ! return (cpackl(-cimagl(w), creall(w))); @ } @ } @ --- 207,216 ---- @ if (isfinite(x) && isfinite(y) && (x > RECIP_SQRT_EPSILON_100 || y > RECIP_SQRT_EPSILON_100)) { @ if (huge+x+y>one) { /* raise inexact flag */ @ ! w = clog_for_large_values(z); @ ! rx = fabsl(cimagl(w)); @ ! ry = creall(w) + M_LN2; @ if (sy == 0) @ ! ry = -ry; @ ! return (cpackl(rx, ry)); @ } @ } @ *************** @ *** 264,268 **** @ } @ @ ! if (ay > 0.5*LDBL_MAX) @ return (cpackl(logl(hypotl(x / L_E, y / L_E)) + 1, atan2l(y, x))); @ @ --- 266,270 ---- @ } @ @ ! if (ax > 0.5*LDBL_MAX) @ return (cpackl(logl(hypotl(x / L_E, y / L_E)) + 1, atan2l(y, x))); @ Some other bugs that I noticed: catrigf.c: % ... % #define MAX_4TH_ROOT 1e9 /* approx pow(FLT_MAX,0.25) */ % #define MIN_4TH_ROOT 1e-9 /* approx pow(FLT_MIN,0.25) */ % #define SQRT_EPSILON_100 1e-6 /* approx (sqrt(FLT_EPSILON)/100) */ % /* 100 is to "play it safe." */ % #define RECIP_SQRT_EPSILON_100 1e6 /* 1/SQRT_EPSILON_100 */ % #define EPSILON_100 1e-9 /* approx FLT_EPSILON/100 */ % #define RECIP_EPSILON_100 1e9 /* 1/EPSILON_100 */ These aren't float constants. Mixing them with floats may give unwanted extra precision and slowness. Most of these should be hex constants, so that they are easier to understand. In clog() I originaly used magic hex constants, but but almost everything was a power of 2 related to FOO_MAX or FOO_MANT_DIG, as above, but it is difficult to translate from those to hex constants (FLT_EPSILON / 128 could be done using token pasting as ((0x1p # FLT_MIN_EXP) * 2 / 128), but square and fourth roots are harder. After changing the classification using bits, all the comparisions with thresholds became comparisons of exponents, and it is now trivial to take roots by dividing the expondent. ld128 clogl() now works with identical code to ld80 clogl(), based on macros in , and the differences for other precisions are minor (I could hide them all using more macros). % ... % static const float % one = 1.00000000000000000000e+00, % huge= 1.00000000000000000000e+30; Using variables instead of macros avoids having to put F suffixes on all float constants. % ... % inline static float % f(float a, float b, float hypot_a_b) % { % if (b < 0) return (0.5 * (hypot_a_b - b)); % if (b == 0) return (0.5*a); % return (0.5 * a*a / (hypot_a_b + b)); % } There a squillions of 0.5's that should be 0.5F's and deserve being named `half' more than 1 deserves being named 'one'. catrigl.c: % #define MAX_4TH_ROOT 1e1200L /* approx pow(LDBL_MAX,0.25) */ % #define MIN_4TH_ROOT 1e-1200L /* approx pow(LDBL_MIN,0.25) */ % #define SQRT_EPSILON_100 1e-13L /* approx (sqrtl(LDBL_EPSILON)/100) */ % #define RECIP_SQRT_EPSILON_100 1e13L /* 1/SQRT_EPSILON_100 */ % #define EPSILON_100 1e-24L /* approx LDBL_EPSILON/100 */ % #define RECIP_EPSILON_100 1e24L /* 1/EPSILON_100 */ Now there is no need for a suffix on the smaller constants. You don't use one for the 0.5's later. The ones related to epsilon look wrong for ld128. LDBL_EPSILON = 2**-(LDBL_MANT_DIG - 1) is way smaller when LDBL_MANT_DIG is 113 than when it is 64. I'm fairly happy with the attached clog() now. All refinements that I tried lately give either less accuracy, lower speed or larger code. Ones that don't quite work are: - write log(ax*ax + ay*ay) * 0.5 = log(ax) + log1p(1 + (ay/ax)**2) * 0.5. This avoids complications when ax is larger or ay is small (after ensuring than ay/ax is not small), but tends to be slower and a bit less accurate. - write ax = 2**k * bx; ay = 2**k * by; log(ax*ax + ay*ay) * 0.5 = k * log(2) + log(bx*bx + by*by) * 0.5. This gives marginally more accuracy, but tends to be slower and a bit more complicated. One complication is that bx*bx + by*by may need another scaling by a factor of 2 or 1/2 to make it between sqrt(2)/2 and sqrt(2). Many changes in this version: % /* Avoid overflow. */ % if (kx >= MAX_EXP - 1) % return (cpack(log(hypot(x * 0x1p-1022, y * 0x1p-1022)) + % (MAX_EXP - 2) * ln2_lo + (MAX_EXP - 2) * ln2_hi, v)); % if (kx >= (MAX_EXP - 1) / 2) % return (cpack(log(hypot(x, y)), v)); 1. Use integer exponenents kx and ky for all classifications. 2. Get all the thresholds right. 3. Scale down to near 1 here, instead of just by a factor of 2. This gives some extra accuracy for no runtime cost. % % /* Reduce inaccuracies and avoid underflow when ax is denormal. */ % if (kx <= MIN_EXP - 2) % return (cpack(log(hypot(x * 0x1p1023, y * 0x1p1023)) + % (MIN_EXP - 2) * ln2_lo + (MIN_EXP - 2) * ln2_hi, v)); 4. Scale up to near 1 here, instead of just by a factor of 2. This gives considerable extra accuracy for no runtime cost. % % /* Avoid remaining underflows (when ax is small but not denormal). */ % if (ky < (MIN_EXP - 1) / 2 + MANT_DIG) % return (cpack(log(hypot(x, y)), v)); 5. Don't scale here. The correct scale factor is ~ 2**-kx for both cases, but that has more overheads. So we only scale up when necessary to avoid losing considerable accuracy (for denormal ax), and let log() do the scaling for other cases. % /* Calculate ax*ax and ay*ay exactly using Dekker's algorithm. */ % t = (double)(ax * (0x1p27 + 1)); % axh = (double)(ax - t) + t; % axl = ax - axh; % ax2h = ax * ax; % ax2l = axh * axh - ax2h + 2 * axh * axl + axl * axl; % t = (double)(ay * (0x1p27 + 1)); % ayh = (double)(ay - t) + t; % ayl = ay - ayh; % ay2h = ay * ay; % ay2l = ayh * ayh - ay2h + 2 * ayh * ayl + ayl * ayl; 6. Additive splitting like I had for clogl() before doesn't work unless ax is near 1. Use the correct Veldkamp algorithm after googling Dekker's algorithms. ax has type double_t, so casting to double avoids compiler bugfeatures at some cost. % sh -= 1; % norm(sh, sl); % norm(ax2l, ay2l); % /* Briggs-Kahan algorithm (except we discard the final low term): */ % norm(sh, ax2l); % norm(sl, ay2l); % t = ax2l + sl; % normF(sh, t); % return (cpack(log1p(ay2l + t + sh) * 0.5, v)); 7. Use a full modernised Dekker's algorithm for the critical case of |z| very near 1 (and for many cases not so near 1). There are 2 Veldkamp splittings, 4 norm() (= 2sum) calls and 2 normF() (= 2sumF) calls on the way here. norm() takes 6 additions and normF() takes 3, so there are 30 additions just for the norm*()'s. But this is only moderately slow (about the same speed as extra branches to avoid doing it all so much). Bruce --0-1116022701-1344877047=:3692 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="cplex.c" Content-Transfer-Encoding: BASE64 Content-ID: <20120814025727.Q3692@besplex.bde.org> Content-Description: Content-Disposition: attachment; filename="cplex.c" I2luY2x1ZGUgPGNvbXBsZXguaD4NCiNpbmNsdWRlIDxmbG9hdC5oPg0KDQoj aW5jbHVkZSAiZnBtYXRoLmgiDQojaW5jbHVkZSAibG9jYWwuaCINCiNpbmNs dWRlICJtYXRoLmgiDQojaW5jbHVkZSAibWF0aF9wcml2YXRlLmgiDQoNCi8q IDJzdW0gYWxnb3JpdGhtLiAqLw0KI3VuZGVmIG5vcm0NCiNkZWZpbmUJbm9y bShhLCBiKSBkbyB7CQlcDQoJX190eXBlb2YoYSkgX19zLCBfX3c7CVwNCgkJ CQlcDQoJX193ID0gKGEpICsgKGIpOwlcDQoJX19zID0gX193IC0gKGEpOwlc DQoJKGIpID0gKChhKSAtIChfX3cgLSBfX3MpKSArICgoYikgLSBfX3MpOyBc DQoJKGEpID0gX193OwkJXA0KfSB3aGlsZSAoMCkNCg0KLyogMnN1bUYgYWxn b3JpdGhtLiAqLw0KI2RlZmluZQlub3JtRihhLCBiKSBkbyB7CVwNCglfX3R5 cGVvZihhKSBfX3c7CVwNCgkJCQlcDQoJX193ID0gKGEpICsgKGIpOwlcDQoJ KGIpID0gKChhKSAtIF9fdykgKyAoYik7IFwNCgkoYSkgPSBfX3c7CQlcDQp9 IHdoaWxlICgwKQ0KDQojZGVmaW5lCU1BTlRfRElHCURCTF9NQU5UX0RJRw0K I2RlZmluZQlNQVhfRVhQCQlEQkxfTUFYX0VYUA0KI2RlZmluZQlNSU5fRVhQ CQlEQkxfTUlOX0VYUA0KDQpzdGF0aWMgY29uc3QgZG91YmxlDQpsbjJfaGkg PSA2LjkzMTQ3MTgwNTU4Mjk4NzFlLTEsCQkvKiAgMHgxNjJlNDJmZWZhMDAw MC4wcC01MyAqLw0KbG4yX2xvID0gMS42NDY1OTQ5NTgyODk3MDgyZS0xMjsJ LyogIDB4MWNmNzlhYmM5ZTNiM2EuMHAtOTIgKi8NCg0KZG91YmxlIGNvbXBs ZXgNCmNsb2coZG91YmxlIGNvbXBsZXggeikNCnsNCglkb3VibGVfdCBheCwg YXgyaCwgYXgybCwgYXhoLCBheGwsIGF5LCBheTJoLCBheTJsLCBheWgsIGF5 bCwgc2gsIHNsLCB0Ow0KCWRvdWJsZSB4LCB5LCB2Ow0KCXVpbnQzMl90IGhh eCwgaGF5Ow0KCWludCBreCwga3k7DQoNCgl4ID0gY3JlYWwoeik7DQoJeSA9 IGNpbWFnKHopOw0KCXYgPSBhdGFuMih5LCB4KTsNCg0KCWF4ID0gZmFicyh4 KTsNCglheSA9IGZhYnMoeSk7DQoJaWYgKGF4IDwgYXkpIHsNCgkJdCA9IGF4 Ow0KCQlheCA9IGF5Ow0KCQlheSA9IHQ7DQoJfQ0KDQoJR0VUX0hJR0hfV09S RChoYXgsIGF4KTsNCglreCA9IChoYXggPj4gMjApIC0gMTAyMzsNCglHRVRf SElHSF9XT1JEKGhheSwgYXkpOw0KCWt5ID0gKGhheSA+PiAyMCkgLSAxMDIz Ow0KDQoJLyogSGFuZGxlIE5hTnMgYW5kIEluZnMgdXNpbmcgdGhlIGdlbmVy YWwgZm9ybXVsYS4gKi8NCglpZiAoa3ggPT0gTUFYX0VYUCB8fCBreSA9PSBN QVhfRVhQKQ0KCQlyZXR1cm4gKGNwYWNrKGxvZyhoeXBvdCh4LCB5KSksIHYp KTsNCg0KCS8qIEF2b2lkIHNwdXJpb3VzIHVuZGVyZmxvdywgYW5kIHJlZHVj ZSBpbmFjY3VyYWNpZXMgd2hlbiBheCBpcyAxLiAqLw0KCWlmIChheCA9PSAx KSB7DQoJCWlmIChreSA8IChNSU5fRVhQIC0gMSkgLyAyKQ0KCQkJcmV0dXJu IChjcGFjaygoYXkgKiAwLjUpICogYXksIHYpKTsNCgkJcmV0dXJuIChjcGFj ayhsb2cxcChheSAqIGF5KSAqIDAuNSwgdikpOw0KCX0NCg0KCS8qIEF2b2lk IHVuZGVyZmxvdyB3aGVuIGF4IGlzIG5vdCBzbWFsbC4gIEFsc28gaGFuZGxl IHplcm8gYXJncy4gKi8NCglpZiAoa3ggLSBreSA+IE1BTlRfRElHIHx8IGF5 ID09IDApDQoJCXJldHVybiAoY3BhY2sobG9nKGF4KSwgdikpOw0KDQoJLyog QXZvaWQgb3ZlcmZsb3cuICovDQoJaWYgKGt4ID49IE1BWF9FWFAgLSAxKQ0K CQlyZXR1cm4gKGNwYWNrKGxvZyhoeXBvdCh4ICogMHgxcC0xMDIyLCB5ICog MHgxcC0xMDIyKSkgKw0KCQkgICAgKE1BWF9FWFAgLSAyKSAqIGxuMl9sbyAr IChNQVhfRVhQIC0gMikgKiBsbjJfaGksIHYpKTsNCglpZiAoa3ggPj0gKE1B WF9FWFAgLSAxKSAvIDIpDQoJCXJldHVybiAoY3BhY2sobG9nKGh5cG90KHgs IHkpKSwgdikpOw0KDQoJLyogUmVkdWNlIGluYWNjdXJhY2llcyBhbmQgYXZv aWQgdW5kZXJmbG93IHdoZW4gYXggaXMgZGVub3JtYWwuICovDQoJaWYgKGt4 IDw9IE1JTl9FWFAgLSAyKQ0KCQlyZXR1cm4gKGNwYWNrKGxvZyhoeXBvdCh4 ICogMHgxcDEwMjMsIHkgKiAweDFwMTAyMykpICsNCgkJICAgIChNSU5fRVhQ IC0gMikgKiBsbjJfbG8gKyAoTUlOX0VYUCAtIDIpICogbG4yX2hpLCB2KSk7 DQoNCgkvKiBBdm9pZCByZW1haW5pbmcgdW5kZXJmbG93cyAod2hlbiBheCBp cyBzbWFsbCBidXQgbm90IGRlbm9ybWFsKS4gKi8NCglpZiAoa3kgPCAoTUlO X0VYUCAtIDEpIC8gMiArIE1BTlRfRElHKQ0KCQlyZXR1cm4gKGNwYWNrKGxv ZyhoeXBvdCh4LCB5KSksIHYpKTsNCg0KCS8qIENhbGN1bGF0ZSBheCpheCBh bmQgYXkqYXkgZXhhY3RseSB1c2luZyBEZWtrZXIncyBhbGdvcml0aG0uICov DQoJdCA9IChkb3VibGUpKGF4ICogKDB4MXAyNyArIDEpKTsNCglheGggPSAo ZG91YmxlKShheCAtIHQpICsgdDsNCglheGwgPSBheCAtIGF4aDsNCglheDJo ID0gYXggKiBheDsNCglheDJsID0gYXhoICogYXhoIC0gYXgyaCArIDIgKiBh eGggKiBheGwgKyBheGwgKiBheGw7DQoJdCA9IChkb3VibGUpKGF5ICogKDB4 MXAyNyArIDEpKTsNCglheWggPSAoZG91YmxlKShheSAtIHQpICsgdDsNCglh eWwgPSBheSAtIGF5aDsNCglheTJoID0gYXkgKiBheTsNCglheTJsID0gYXlo ICogYXloIC0gYXkyaCArIDIgKiBheWggKiBheWwgKyBheWwgKiBheWw7DQoN CgkvKg0KCSAqIFdoZW4gbG9nKHx6fCkgaXMgZmFyIGZyb20gMSwgYWNjdXJh Y3kgaW4gY2FsY3VsYXRpbmcgdGhlIHN1bQ0KCSAqIG9mIHRoZSBzcXVhcmVz IGlzIG5vdCB2ZXJ5IGltcG9ydGFudCBzaW5jZSBsb2coKSByZWR1Y2VzDQoJ ICogaW5hY2N1cmFjaWVzLiAgV2UgZGVwZW5kZWQgb24gdGhpcyB0byB1c2Ug dGhlIGdlbmVyYWwNCgkgKiBmb3JtdWxhIHdoZW4gbG9nKHx6fCkgaXMgdmVy eSBmYXIgZnJvbSAxLiAgV2hlbiBsb2cofHp8KSBpcw0KCSAqIG1vZGVyYXRl bHkgZmFyIGZyb20gMSwgd2UgZ28gdGhyb3VnaCB0aGUgZXh0cmEtcHJlY2lz aW9uDQoJICogY2FsY3VsYXRpb25zIHRvIHJlZHVjZSBicmFuY2hlcyBhbmQg Z2FpbiBhIGxpdHRsZSBhY2N1cmFjeS4NCgkgKg0KCSAqIFdoZW4gfHp8IGlz IG5lYXIgMSwgd2Ugc3VidHJhY3QgMSBhbmQgdXNlIGxvZzFwKCkgYW5kIGRv bid0DQoJICogbGVhdmUgaXQgdG8gbG9nKCkgdG8gc3VidHJhY3QgMSwgc2lu Y2Ugd2UgZ2FpbiBhdCBsZWFzdCAxIGJpdA0KCSAqIG9mIGFjY3VyYWN5IGlu IHRoaXMgd2F5Lg0KCSAqDQoJICogV2hlbiB8enwgaXMgdmVyeSBuZWFyIDEs IHN1YnRyYWN0aW5nIDEgY2FuIGNhbmNlbCBhbG1vc3QNCgkgKiAzKk1BTlRf RElHIGJpdHMuICBXZSBhcnJhbmdlIHRoYXQgc3VidHJhY3RpbmcgMSBpcyBl eGFjdCBpbg0KCSAqIGRvdWJsZWQgcHJlY2lzaW9uLCBhbmQgdGhlbiBkbyB0 aGUgcmVzdCBvZiB0aGUgY2FsY3VsYXRpb24NCgkgKiBpbiBzbG9wcHkgZG91 YmxlZCBwcmVjaXNpb24uICBBbHRob3VnaCBsYXJnZSBjYW5jZWxhdGlvbnMN CgkgKiBvZnRlbiBsb3NlIGxvdHMgb2YgYWNjdXJhY3ksIGhlcmUgdGhlIGZp bmFsIHJlc3VsdCBpcyBleGFjdA0KCSAqIGluIGRvdWJsZWQgcHJlY2lzaW9u IGlmIHRoZSBsYXJnZSBjYWxjdWxhdGlvbiBvY2N1cnMgKGJlY2F1c2UNCgkg KiB0aGVuIGl0IGlzIGV4YWN0IGluIHRyaXBsZWQgcHJlY2lzaW9uIGFuZCB0 aGUgY2FuY2VsYXRpb24NCgkgKiByZW1vdmVzIGVub3VnaCBiaXRzIHRvIGZp dCBpbiBkb3VibGVkIHByZWNpc2lvbikuICBUaHVzIHRoZQ0KCSAqIHJlc3Vs dCBpcyBhY2N1cmF0ZSBpbiBzbG9wcHkgZG91YmxlZCBwcmVjaXNpb24sIGFu ZCB0aGUgb25seQ0KCSAqIHNpZ25pZmljYW50IGxvc3Mgb2YgYWNjdXJhY3kg aXMgd2hlbiBpdCBpcyBzdW1tZWQgYW5kIHBhc3NlZA0KCSAqIHRvIGxvZzFw KCkuDQoJICovDQoJc2ggPSBheDJoOw0KCXNsID0gYXkyaDsNCglub3JtRihz aCwgc2wpOw0KCWlmIChzaCA8IDAuNSB8fCBzaCA+PSAzKQ0KCQlyZXR1cm4g KGNwYWNrKGxvZyhheTJsICsgYXgybCArIHNsICsgc2gpICogMC41LCB2KSk7 DQoJc2ggLT0gMTsNCglub3JtKHNoLCBzbCk7DQoJbm9ybShheDJsLCBheTJs KTsNCgkvKiBCcmlnZ3MtS2FoYW4gYWxnb3JpdGhtIChleGNlcHQgd2UgZGlz Y2FyZCB0aGUgZmluYWwgbG93IHRlcm0pOiAqLw0KCW5vcm0oc2gsIGF4Mmwp Ow0KCW5vcm0oc2wsIGF5MmwpOw0KCXQgPSBheDJsICsgc2w7DQoJbm9ybUYo c2gsIHQpOw0KCXJldHVybiAoY3BhY2sobG9nMXAoYXkybCArIHQgKyBzaCkg KiAwLjUsIHYpKTsNCn0NCg0KI2lmIChMREJMX01BTlRfRElHID09IDUzKQ0K X193ZWFrX3JlZmVyZW5jZShjbG9nLCBjbG9nbCk7DQojZW5kaWYNCg0KI3Vu ZGVmIE1BTlRfRElHDQojZGVmaW5lCU1BTlRfRElHCUZMVF9NQU5UX0RJRw0K I3VuZGVmIE1BWF9FWFANCiNkZWZpbmUJTUFYX0VYUAkJRkxUX01BWF9FWFAN CiN1bmRlZiBNSU5fRVhQDQojZGVmaW5lCU1JTl9FWFAJCUZMVF9NSU5fRVhQ DQoNCnN0YXRpYyBjb25zdCBmbG9hdA0KbG4yZl9oaSA9ICA2LjkzMTQ1NzUx OTVlLTEsCQkvKiAgMHhiMTcyMDAuMHAtMjQgKi8NCmxuMmZfbG8gPSAgMS40 Mjg2MDY3NjUzZS02OwkJLyogIDB4YmZiZThlLjBwLTQzICovDQoNCmZsb2F0 IGNvbXBsZXgNCmNsb2dmKGZsb2F0IGNvbXBsZXggeikNCnsNCglmbG9hdF90 IGF4LCBheDJoLCBheDJsLCBheGgsIGF4bCwgYXksIGF5MmgsIGF5MmwsIGF5 aCwgYXlsLCBzaCwgc2wsIHQ7DQoJZmxvYXQgeCwgeSwgdjsNCgl1aW50MzJf dCBoYXgsIGhheTsNCglpbnQga3gsIGt5Ow0KDQoJeCA9IGNyZWFsZih6KTsN Cgl5ID0gY2ltYWdmKHopOw0KCXYgPSBhdGFuMmYoeSwgeCk7DQoNCglheCA9 IGZhYnNmKHgpOw0KCWF5ID0gZmFic2YoeSk7DQoJaWYgKGF4IDwgYXkpIHsN CgkJdCA9IGF4Ow0KCQlheCA9IGF5Ow0KCQlheSA9IHQ7DQoJfQ0KDQoJR0VU X0ZMT0FUX1dPUkQoaGF4LCBheCk7DQoJa3ggPSAoaGF4ID4+IDIzKSAtIDEy NzsNCglHRVRfRkxPQVRfV09SRChoYXksIGF5KTsNCglreSA9IChoYXkgPj4g MjMpIC0gMTI3Ow0KDQoJLyogSGFuZGxlIE5hTnMgYW5kIEluZnMgdXNpbmcg dGhlIGdlbmVyYWwgZm9ybXVsYS4gKi8NCglpZiAoa3ggPT0gTUFYX0VYUCB8 fCBreSA9PSBNQVhfRVhQKQ0KCQlyZXR1cm4gKGNwYWNrZihsb2dmKGh5cG90 Zih4LCB5KSksIHYpKTsNCg0KCS8qIEF2b2lkIHNwdXJpb3VzIHVuZGVyZmxv dywgYW5kIHJlZHVjZSBpbmFjY3VyYWNpZXMgd2hlbiBheCBpcyAxLiAqLw0K CWlmIChoYXggPT0gMHgzZjgwMDAwMCkgew0KCQlpZiAoa3kgPCAoTUlOX0VY UCAtIDEpIC8gMikNCgkJCXJldHVybiAoY3BhY2tmKChheSAqIDAuNUYpICog YXksIHYpKTsNCgkJcmV0dXJuIChjcGFja2YobG9nMXBmKGF5ICogYXkpICog MC41RiwgdikpOw0KCX0NCg0KCS8qIEF2b2lkIHVuZGVyZmxvdyB3aGVuIGF4 IGlzIG5vdCBzbWFsbC4gIEFsc28gaGFuZGxlIHplcm8gYXJncy4gKi8NCglp ZiAoa3ggLSBreSA+IE1BTlRfRElHIHx8IGhheSA9PSAwKQ0KCQlyZXR1cm4g KGNwYWNrZihsb2dmKGF4KSwgdikpOw0KDQoJLyogQXZvaWQgb3ZlcmZsb3cu ICovDQoJaWYgKGt4ID49IE1BWF9FWFAgLSAxKQ0KCQlyZXR1cm4gKGNwYWNr Zihsb2dmKGh5cG90Zih4ICogMHgxcC0xMjZGLCB5ICogMHgxcC0xMjZGKSkg Kw0KCQkgICAgKE1BWF9FWFAgLSAyKSAqIGxuMl9sbyArIChNQVhfRVhQIC0g MikgKiBsbjJfaGksIHYpKTsNCglpZiAoa3ggPj0gKE1BWF9FWFAgLSAxKSAv IDIpDQoJCXJldHVybiAoY3BhY2tmKGxvZ2YoaHlwb3RmKHgsIHkpKSwgdikp Ow0KDQoJLyogUmVkdWNlIGluYWNjdXJhY2llcyBhbmQgYXZvaWQgdW5kZXJm bG93IHdoZW4gYXggaXMgZGVub3JtYWwuICovDQoJaWYgKGt4IDw9IE1JTl9F WFAgLSAyKQ0KCQlyZXR1cm4gKGNwYWNrZihsb2dmKGh5cG90Zih4ICogMHgx cDEyN0YsIHkgKiAweDFwMTI3RikpICsNCgkJICAgIChNSU5fRVhQIC0gMikg KiBsbjJmX2xvICsgKE1JTl9FWFAgLSAyKSAqIGxuMmZfaGksIHYpKTsNCg0K CS8qIEF2b2lkIHJlbWFpbmluZyB1bmRlcmZsb3dzICh3aGVuIGF4IGlzIHNt YWxsIGJ1dCBub3QgZGVub3JtYWwpLiAqLw0KCWlmIChreSA8IChNSU5fRVhQ IC0gMSkgLyAyICsgTUFOVF9ESUcpDQoJCXJldHVybiAoY3BhY2tmKGxvZ2Yo aHlwb3RmKHgsIHkpKSwgdikpOw0KDQoJLyogQ2FsY3VsYXRlIGF4KmF4IGFu ZCBheSpheSBleGFjdGx5IHVzaW5nIERla2tlcidzIGFsZ29yaXRobS4gKi8N Cgl0ID0gKGZsb2F0KShheCAqICgweDFwMTJGICsgMSkpOw0KCWF4aCA9IChm bG9hdCkoYXggLSB0KSArIHQ7DQoJYXhsID0gYXggLSBheGg7DQoJYXgyaCA9 IGF4ICogYXg7DQoJYXgybCA9IGF4aCAqIGF4aCAtIGF4MmggKyAyICogYXho ICogYXhsICsgYXhsICogYXhsOw0KCXQgPSAoZmxvYXQpKGF5ICogKDB4MXAx MkYgKyAxKSk7DQoJYXloID0gKGZsb2F0KShheSAtIHQpICsgdDsNCglheWwg PSBheSAtIGF5aDsNCglheTJoID0gYXkgKiBheTsNCglheTJsID0gYXloICog YXloIC0gYXkyaCArIDIgKiBheWggKiBheWwgKyBheWwgKiBheWw7DQoNCgkv Kg0KCSAqIFdoZW4gbG9nKHx6fCkgaXMgZmFyIGZyb20gMSwgYWNjdXJhY3kg aW4gY2FsY3VsYXRpbmcgdGhlIHN1bQ0KCSAqIG9mIHRoZSBzcXVhcmVzIGlz IG5vdCB2ZXJ5IGltcG9ydGFudCBzaW5jZSBsb2coKSByZWR1Y2VzDQoJICog aW5hY2N1cmFjaWVzLiAgV2UgZGVwZW5kZWQgb24gdGhpcyB0byB1c2UgdGhl IGdlbmVyYWwNCgkgKiBmb3JtdWxhIHdoZW4gbG9nKHx6fCkgaXMgdmVyeSBm YXIgZnJvbSAxLiAgV2hlbiBsb2cofHp8KSBpcw0KCSAqIG1vZGVyYXRlbHkg ZmFyIGZyb20gMSwgd2UgZ28gdGhyb3VnaCB0aGUgZXh0cmEtcHJlY2lzaW9u DQoJICogY2FsY3VsYXRpb25zIHRvIHJlZHVjZSBicmFuY2hlcyBhbmQgZ2Fp biBhIGxpdHRsZSBhY2N1cmFjeS4NCgkgKg0KCSAqIFdoZW4gfHp8IGlzIG5l YXIgMSwgd2Ugc3VidHJhY3QgMSBhbmQgdXNlIGxvZzFwKCkgYW5kIGRvbid0 DQoJICogbGVhdmUgaXQgdG8gbG9nKCkgdG8gc3VidHJhY3QgMSwgc2luY2Ug d2UgZ2FpbiBhdCBsZWFzdCAxIGJpdA0KCSAqIG9mIGFjY3VyYWN5IGluIHRo aXMgd2F5Lg0KCSAqDQoJICogV2hlbiB8enwgaXMgdmVyeSBuZWFyIDEsIHN1 YnRyYWN0aW5nIDEgY2FuIGNhbmNlbCBhbG1vc3QNCgkgKiAzKk1BTlRfRElH IGJpdHMuICBXZSBhcnJhbmdlIHRoYXQgc3VidHJhY3RpbmcgMSBpcyBleGFj dCBpbg0KCSAqIGRvdWJsZWQgcHJlY2lzaW9uLCBhbmQgdGhlbiBkbyB0aGUg cmVzdCBvZiB0aGUgY2FsY3VsYXRpb24NCgkgKiBpbiBzbG9wcHkgZG91Ymxl ZCBwcmVjaXNpb24uICBBbHRob3VnaCBsYXJnZSBjYW5jZWxhdGlvbnMNCgkg KiBvZnRlbiBsb3NlIGxvdHMgb2YgYWNjdXJhY3ksIGhlcmUgdGhlIGZpbmFs IHJlc3VsdCBpcyBleGFjdA0KCSAqIGluIGRvdWJsZWQgcHJlY2lzaW9uIGlm IHRoZSBsYXJnZSBjYWxjdWxhdGlvbiBvY2N1cnMgKGJlY2F1c2UNCgkgKiB0 aGVuIGl0IGlzIGV4YWN0IGluIHRyaXBsZWQgcHJlY2lzaW9uIGFuZCB0aGUg Y2FuY2VsYXRpb24NCgkgKiByZW1vdmVzIGVub3VnaCBiaXRzIHRvIGZpdCBp biBkb3VibGVkIHByZWNpc2lvbikuICBUaHVzIHRoZQ0KCSAqIHJlc3VsdCBp cyBhY2N1cmF0ZSBpbiBzbG9wcHkgZG91YmxlZCBwcmVjaXNpb24sIGFuZCB0 aGUgb25seQ0KCSAqIHNpZ25pZmljYW50IGxvc3Mgb2YgYWNjdXJhY3kgaXMg d2hlbiBpdCBpcyBzdW1tZWQgYW5kIHBhc3NlZA0KCSAqIHRvIGxvZzFwKCku DQoJICovDQoJc2ggPSBheDJoOw0KCXNsID0gYXkyaDsNCglub3JtRihzaCwg c2wpOw0KCWlmIChzaCA8IDAuNUYgfHwgc2ggPj0gMykNCgkJcmV0dXJuIChj cGFja2YobG9nZihheTJsICsgYXgybCArIHNsICsgc2gpICogMC41Riwgdikp Ow0KCXNoIC09IDE7DQoJbm9ybShzaCwgc2wpOw0KCW5vcm0oYXgybCwgYXky bCk7DQoJLyogQnJpZ2dzLUthaGFuIGFsZ29yaXRobSAoZXhjZXB0IHdlIGRp c2NhcmQgdGhlIGZpbmFsIGxvdyB0ZXJtKTogKi8NCglub3JtKHNoLCBheDJs KTsNCglub3JtKHNsLCBheTJsKTsNCgl0ID0gYXgybCArIHNsOw0KCW5vcm1G KHNoLCB0KTsNCglyZXR1cm4gKGNwYWNrZihsb2cxcGYoYXkybCArIHQgKyBz aCkgKiAwLjVGLCB2KSk7DQp9DQoNCiN1bmRlZiBNQU5UX0RJRw0KI2RlZmlu ZQlNQU5UX0RJRwlMREJMX01BTlRfRElHDQojdW5kZWYgTUFYX0VYUA0KI2Rl ZmluZQlNQVhfRVhQCQlMREJMX01BWF9FWFANCiN1bmRlZiBNSU5fRVhQDQoj ZGVmaW5lCU1JTl9FWFAJCUxEQkxfTUlOX0VYUA0KDQpsb25nIGRvdWJsZSBj b21wbGV4DQpjbG9nbChsb25nIGRvdWJsZSBjb21wbGV4IHopDQp7DQoJbG9u ZyBkb3VibGUgYXgsIGF4MmgsIGF4MmwsIGF4aCwgYXhsLCBheSwgYXkyaCwg YXkybCwgYXloLCBheWw7DQoJbG9uZyBkb3VibGUgc2gsIHNsLCB0Ow0KCWxv bmcgZG91YmxlIHgsIHksIHY7DQoJdWludDE2X3QgaGF4LCBoYXk7DQoJaW50 IGt4LCBreTsNCg0KCXggPSBjcmVhbGwoeik7DQoJeSA9IGNpbWFnbCh6KTsN Cgl2ID0gYXRhbjJsKHksIHgpOw0KDQoJYXggPSBmYWJzbCh4KTsNCglheSA9 IGZhYnNsKHkpOw0KCWlmIChheCA8IGF5KSB7DQoJCXQgPSBheDsNCgkJYXgg PSBheTsNCgkJYXkgPSB0Ow0KCX0NCg0KCUdFVF9MREJMX0VYUFNJR04oaGF4 LCBheCk7DQoJa3ggPSBoYXggLSAxNjM4MzsNCglHRVRfTERCTF9FWFBTSUdO KGhheSwgYXkpOw0KCWt5ID0gaGF5IC0gMTYzODM7DQoNCgkvKiBIYW5kbGUg TmFOcyBhbmQgSW5mcyB1c2luZyB0aGUgZ2VuZXJhbCBmb3JtdWxhLiAqLw0K CWlmIChreCA9PSBNQVhfRVhQIHx8IGt5ID09IE1BWF9FWFApDQoJCXJldHVy biAoY3BhY2tsKGxvZ2woaHlwb3RsKHgsIHkpKSwgdikpOw0KDQoJLyogQXZv aWQgc3B1cmlvdXMgdW5kZXJmbG93LCBhbmQgcmVkdWNlIGluYWNjdXJhY2ll cyB3aGVuIGF4IGlzIDEuICovDQoJaWYgKGF4ID09IDEpIHsNCgkJaWYgKGt5 IDwgKE1JTl9FWFAgLSAxKSAvIDIpDQoJCQlyZXR1cm4gKGNwYWNrbCgoYXkg KiAwLjUpICogYXksIHYpKTsNCgkJcmV0dXJuIChjcGFja2wobG9nMXBsKGF5 ICogYXkpICogMC41LCB2KSk7DQoJfQ0KDQoJLyogQXZvaWQgdW5kZXJmbG93 IHdoZW4gYXggaXMgbm90IHNtYWxsLiAgQWxzbyBoYW5kbGUgemVybyBhcmdz LiAqLw0KCWlmIChreCAtIGt5ID4gTUFOVF9ESUcgfHwgYXkgPT0gMCkNCgkJ cmV0dXJuIChjcGFja2wobG9nbChheCksIHYpKTsNCg0KCS8qIEF2b2lkIG92 ZXJmbG93LiAqLw0KCWlmIChreCA+PSBNQVhfRVhQIC0gMSkNCgkJcmV0dXJu IChjcGFja2wobG9nbChoeXBvdGwoeCAqIDB4MXAtMTYzODJMLCB5ICogMHgx cC0xNjM4MkwpKSArDQoJCSAgICAoTUFYX0VYUCAtIDIpICogbG4yX2xvICsg KE1BWF9FWFAgLSAyKSAqIGxuMl9oaSwgdikpOw0KCWlmIChreCA+PSAoTUFY X0VYUCAtIDEpIC8gMikNCgkJcmV0dXJuIChjcGFja2wobG9nbChoeXBvdGwo eCwgeSkpLCB2KSk7DQoNCgkvKiBSZWR1Y2UgaW5hY2N1cmFjaWVzIGFuZCBh dm9pZCB1bmRlcmZsb3cgd2hlbiBheCBpcyBkZW5vcm1hbC4gKi8NCglpZiAo a3ggPD0gTUlOX0VYUCAtIDIpDQoJCXJldHVybiAoY3BhY2tsKGxvZ2woaHlw b3RsKHggKiAweDFwMTYzODNMLCB5ICogMHgxcDE2MzgzTCkpICsNCgkJICAg IChNSU5fRVhQIC0gMikgKiBsbjJfbG8gKyAoTUlOX0VYUCAtIDIpICogbG4y X2hpLCB2KSk7DQoNCgkvKiBBdm9pZCByZW1haW5pbmcgdW5kZXJmbG93cyAo d2hlbiBheCBpcyBzbWFsbCBidXQgbm90IGRlbm9ybWFsKS4gKi8NCglpZiAo a3kgPCAoTUlOX0VYUCAtIDEpIC8gMiArIE1BTlRfRElHKQ0KCQlyZXR1cm4g KGNwYWNrbChsb2dsKGh5cG90bCh4LCB5KSksIHYpKTsNCg0KCS8qIENhbGN1 bGF0ZSBheCpheCBhbmQgYXkqYXkgZXhhY3RseSB1c2luZyBEZWtrZXIncyBh bGdvcml0aG0uICovDQoJdCA9IChsb25nIGRvdWJsZSkoYXggKiAoMHgxcDMy ICsgMSkpOw0KCWF4aCA9IChsb25nIGRvdWJsZSkoYXggLSB0KSArIHQ7DQoJ YXhsID0gYXggLSBheGg7DQoJYXgyaCA9IGF4ICogYXg7DQoJYXgybCA9IGF4 aCAqIGF4aCAtIGF4MmggKyAyICogYXhoICogYXhsICsgYXhsICogYXhsOw0K CXQgPSAobG9uZyBkb3VibGUpKGF5ICogKDB4MXAzMiArIDEpKTsNCglheWgg PSAobG9uZyBkb3VibGUpKGF5IC0gdCkgKyB0Ow0KCWF5bCA9IGF5IC0gYXlo Ow0KCWF5MmggPSBheSAqIGF5Ow0KCWF5MmwgPSBheWggKiBheWggLSBheTJo ICsgMiAqIGF5aCAqIGF5bCArIGF5bCAqIGF5bDsNCg0KCS8qDQoJICogV2hl biBsb2cofHp8KSBpcyBmYXIgZnJvbSAxLCBhY2N1cmFjeSBpbiBjYWxjdWxh dGluZyB0aGUgc3VtDQoJICogb2YgdGhlIHNxdWFyZXMgaXMgbm90IHZlcnkg aW1wb3J0YW50IHNpbmNlIGxvZygpIHJlZHVjZXMNCgkgKiBpbmFjY3VyYWNp ZXMuICBXZSBkZXBlbmRlZCBvbiB0aGlzIHRvIHVzZSB0aGUgZ2VuZXJhbA0K CSAqIGZvcm11bGEgd2hlbiBsb2cofHp8KSBpcyB2ZXJ5IGZhciBmcm9tIDEu ICBXaGVuIGxvZyh8enwpIGlzDQoJICogbW9kZXJhdGVseSBmYXIgZnJvbSAx LCB3ZSBnbyB0aHJvdWdoIHRoZSBleHRyYS1wcmVjaXNpb24NCgkgKiBjYWxj dWxhdGlvbnMgdG8gcmVkdWNlIGJyYW5jaGVzIGFuZCBnYWluIGEgbGl0dGxl IGFjY3VyYWN5Lg0KCSAqDQoJICogV2hlbiB8enwgaXMgbmVhciAxLCB3ZSBz dWJ0cmFjdCAxIGFuZCB1c2UgbG9nMXAoKSBhbmQgZG9uJ3QNCgkgKiBsZWF2 ZSBpdCB0byBsb2coKSB0byBzdWJ0cmFjdCAxLCBzaW5jZSB3ZSBnYWluIGF0 IGxlYXN0IDEgYml0DQoJICogb2YgYWNjdXJhY3kgaW4gdGhpcyB3YXkuDQoJ ICoNCgkgKiBXaGVuIHx6fCBpcyB2ZXJ5IG5lYXIgMSwgc3VidHJhY3Rpbmcg MSBjYW4gY2FuY2VsIGFsbW9zdA0KCSAqIDMqTUFOVF9ESUcgYml0cy4gIFdl IGFycmFuZ2UgdGhhdCBzdWJ0cmFjdGluZyAxIGlzIGV4YWN0IGluDQoJICog ZG91YmxlZCBwcmVjaXNpb24sIGFuZCB0aGVuIGRvIHRoZSByZXN0IG9mIHRo ZSBjYWxjdWxhdGlvbg0KCSAqIGluIHNsb3BweSBkb3VibGVkIHByZWNpc2lv bi4gIEFsdGhvdWdoIGxhcmdlIGNhbmNlbGF0aW9ucw0KCSAqIG9mdGVuIGxv c2UgbG90cyBvZiBhY2N1cmFjeSwgaGVyZSB0aGUgZmluYWwgcmVzdWx0IGlz IGV4YWN0DQoJICogaW4gZG91YmxlZCBwcmVjaXNpb24gaWYgdGhlIGxhcmdl IGNhbGN1bGF0aW9uIG9jY3VycyAoYmVjYXVzZQ0KCSAqIHRoZW4gaXQgaXMg ZXhhY3QgaW4gdHJpcGxlZCBwcmVjaXNpb24gYW5kIHRoZSBjYW5jZWxhdGlv bg0KCSAqIHJlbW92ZXMgZW5vdWdoIGJpdHMgdG8gZml0IGluIGRvdWJsZWQg cHJlY2lzaW9uKS4gIFRodXMgdGhlDQoJICogcmVzdWx0IGlzIGFjY3VyYXRl IGluIHNsb3BweSBkb3VibGVkIHByZWNpc2lvbiwgYW5kIHRoZSBvbmx5DQoJ ICogc2lnbmlmaWNhbnQgbG9zcyBvZiBhY2N1cmFjeSBpcyB3aGVuIGl0IGlz IHN1bW1lZCBhbmQgcGFzc2VkDQoJICogdG8gbG9nMXAoKS4NCgkgKi8NCglz aCA9IGF4Mmg7DQoJc2wgPSBheTJoOw0KCW5vcm1GKHNoLCBzbCk7DQoJaWYg KHNoIDwgMC41IHx8IHNoID49IDMpDQoJCXJldHVybiAoY3BhY2tsKGxvZ2wo YXkybCArIGF4MmwgKyBzbCArIHNoKSAqIDAuNSwgdikpOw0KCXNoIC09IDE7 DQoJbm9ybShzaCwgc2wpOw0KCW5vcm0oYXgybCwgYXkybCk7DQoJLyogQnJp Z2dzLUthaGFuIGFsZ29yaXRobSAoZXhjZXB0IHdlIGRpc2NhcmQgdGhlIGZp bmFsIGxvdyB0ZXJtKTogKi8NCglub3JtKHNoLCBheDJsKTsNCglub3JtKHNs LCBheTJsKTsNCgl0ID0gYXgybCArIHNsOw0KCW5vcm1GKHNoLCB0KTsNCgly ZXR1cm4gKGNwYWNrbChsb2cxcGwoYXkybCArIHQgKyBzaCkgKiAwLjUsIHYp KTsNCn0NCg0KI2RlZmluZQlHRU4oZnVuYywgdHlwZSwgbHR5cGUsIHBhcnQs IGxwYXJ0KQlcDQp0eXBlCQkJCQkJXA0KbHBhcnQgIyMgYyAjIyBmdW5jICMj IGx0eXBlKHR5cGUgeCwgdHlwZSB5KQlcDQp7CQkJCQkJXA0KCXR5cGUgY29t cGxleCB6OwkJCQlcDQoJdHlwZSBjb21wbGV4IHc7CQkJCVwNCgkJCQkJCVwN Cgl6ID0gY3BhY2sgIyMgbHR5cGUoeCwgeSk7CQlcDQoJdyA9IGMgIyMgZnVu YyAjIyBsdHlwZSh6KTsJCVwNCglyZXR1cm4gKGMgIyMgcGFydCAjIyBsdHlw ZSh3KSk7CQlcDQp9DQoNCiNkZWZpbmUJR0VOMyhmdW5jKQkJCVwNCkdFTihm dW5jLCBkb3VibGUsICwgcmVhbCwgcikJCVwNCkdFTihmdW5jLCBkb3VibGUs ICwgaW1hZywgaSkJCVwNCkdFTihmdW5jLCBmbG9hdCwgZiwgcmVhbCwgcikJ CVwNCkdFTihmdW5jLCBmbG9hdCwgZiwgaW1hZywgaSkJCVwNCkdFTihmdW5j LCBsb25nIGRvdWJsZSwgbCwgcmVhbCwgcikJXA0KR0VOKGZ1bmMsIGxvbmcg ZG91YmxlLCBsLCBpbWFnLCBpKQ0KDQpHRU4zKGFjb3MpDQpHRU4zKGFjb3No KQ0KR0VOMyhhc2luKQ0KR0VOMyhhc2luaCkNCkdFTjMoYXRhbikNCkdFTjMo YXRhbmgpDQpHRU4zKGxvZykNCg== --0-1116022701-1344877047=:3692 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="catrig.diff" Content-Transfer-Encoding: BASE64 Content-ID: <20120814025727.M3692@besplex.bde.org> Content-Description: Content-Disposition: attachment; filename="catrig.diff" ZGlmZiAtYzIgY2F0cmlnLmN+IGNhdHJpZy5jDQoqKiogY2F0cmlnLmN+CVN1 biBBdWcgMTIgMTc6Mjk6MTggMjAxMg0KLS0tIGNhdHJpZy5jCU1vbiBBdWcg MTMgMTI6MDc6MDkgMjAxMg0KKioqKioqKioqKioqKioqDQoqKiogMjY1LDI2 OSAqKioqDQogIAkJcmV0dXJuOw0KICAJfQ0KISAJaWYgKHkgPCBNSU5fNFRI X1JPT1QpIHsNCiAgCQkvKg0KICAJCSAqIEF2b2lkIGEgcG9zc2libGUgdW5k ZXJmbG93IGNhdXNlZCBieSB5L0EuICBGb3IgY2FzaW5oIHRoaXMNCi0tLSAy NjUsMjY5IC0tLS0NCiAgCQlyZXR1cm47DQogIAl9DQohIAlpZiAoIUlTTkFO KHgpICYmIHkgPCBNSU5fNFRIX1JPT1QpIHsNCiAgCQkvKg0KICAJCSAqIEF2 b2lkIGEgcG9zc2libGUgdW5kZXJmbG93IGNhdXNlZCBieSB5L0EuICBGb3Ig Y2FzaW5oIHRoaXMNCioqKioqKioqKioqKioqKg0KKioqIDQwOCw0MTYgKioq Kg0KICANCiAgCWlmIChJU0ZJTklURShieCkgJiYgSVNGSU5JVEUoYnkpICYm ICh4ID4gUkVDSVBfU1FSVF9FUFNJTE9OXzEwMCB8fCB5ID4gUkVDSVBfU1FS VF9FUFNJTE9OXzEwMCkpIHsNCiEgCQlpZiAoaHVnZSt4K3k+b25lKSB7IC8q IHJhaXNlIGluZXhhY3QgZmxhZyAqLw0KISAJCQl3ID0gY2xvZ19mb3JfbGFy Z2VfdmFsdWVzKHopICsgTV9MTjI7DQogIAkJCWlmIChzeSA9PSAwKQ0KISAJ CQkJcmV0dXJuIChjcGFjayhjaW1hZyh3KSwgLWNyZWFsKHcpKSk7DQohIAkJ CXJldHVybiAoY3BhY2soLWNpbWFnKHcpLCBjcmVhbCh3KSkpOw0KICAJCX0N CiAgCX0NCi0tLSA0MDgsNDIwIC0tLS0NCiAgDQogIAlpZiAoSVNGSU5JVEUo YngpICYmIElTRklOSVRFKGJ5KSAmJiAoeCA+IFJFQ0lQX1NRUlRfRVBTSUxP Tl8xMDAgfHwgeSA+IFJFQ0lQX1NRUlRfRVBTSUxPTl8xMDApKSB7DQohIAkJ LyogWFhYIGZvbGxvd2luZyBjYW4gYWxzbyByYWlzZSBvdmVyZmxvdyAqLw0K ISAJCWlmIChodWdlK3greT5vbmUpIHsgLyogcmFpc2UgaW5leGFjdCAqLw0K ISAJCQl3ID0gY2xvZ19mb3JfbGFyZ2VfdmFsdWVzKHopOw0KISAJCQkvKiBD YW4ndCBhZGQgTV9MTjIgdG8gdyBzaW5jZSBpdCBzaG91bGQgY2xvYmJlciAt MCpJLiAqLw0KISAJCQlyeCA9IGZhYnMoY2ltYWcodykpOw0KISAJCQlyeSA9 IGNyZWFsKHcpICsgTV9MTjI7DQogIAkJCWlmIChzeSA9PSAwKQ0KISAJCQkJ cnkgPSAtcnk7DQohIAkJCXJldHVybiAoY3BhY2socngsIHJ5KSk7DQogIAkJ fQ0KICAJfQ0KKioqKioqKioqKioqKioqDQoqKiogNDgyLDQ4NiAqKioqDQog IAkgKiBidXQgdGhpcyBjYXNlIHNob3VsZCBoYXBwZW4gZXh0cmVtZWx5IHJh cmVseS4NCiAgCSAqLw0KISAJaWYgKGF5ID4gMC41KkRCTF9NQVgpDQogIAkJ cmV0dXJuIChjcGFjayhsb2coaHlwb3QoeCAvIE1fRSwgeSAvIE1fRSkpICsg MSwgYXRhbjIoeSwgeCkpKTsNCiAgDQotLS0gNDg2LDQ5MCAtLS0tDQogIAkg KiBidXQgdGhpcyBjYXNlIHNob3VsZCBoYXBwZW4gZXh0cmVtZWx5IHJhcmVs eS4NCiAgCSAqLw0KISAJaWYgKGF4ID4gMC41KkRCTF9NQVgpDQogIAkJcmV0 dXJuIChjcGFjayhsb2coaHlwb3QoeCAvIE1fRSwgeSAvIE1fRSkpICsgMSwg YXRhbjIoeSwgeCkpKTsNCiAgDQpkaWZmIC1jMiBjYXRyaWdmLmN+IGNhdHJp Z2YuYw0KKioqIGNhdHJpZ2YuY34JU3VuIEF1ZyAxMiAxNzowMDo1MiAyMDEy DQotLS0gY2F0cmlnZi5jCU1vbiBBdWcgMTMgMTQ6MTQ6NDIgMjAxMg0KKioq KioqKioqKioqKioqDQoqKiogMTM4LDE0MiAqKioqDQogIAkJcmV0dXJuOw0K ICAJfQ0KISAJaWYgKHkgPCBNSU5fNFRIX1JPT1QpIHsNCiAgCQkqQl9pc191 c2FibGUgPSAwOw0KICAJCWlmICgoaW50KXk9PTApIC8qIHJhaXNlIGluZXhh Y3QgZmxhZyAqLw0KLS0tIDEzOCwxNDIgLS0tLQ0KICAJCXJldHVybjsNCiAg CX0NCiEgCWlmICghaXNuYW4oeCkgJiYgeSA8IE1JTl80VEhfUk9PVCkgew0K ICAJCSpCX2lzX3VzYWJsZSA9IDA7DQogIAkJaWYgKChpbnQpeT09MCkgLyog cmFpc2UgaW5leGFjdCBmbGFnICovDQoqKioqKioqKioqKioqKioNCioqKiAy MzMsMjQwICoqKioNCiAgCWlmIChpc2Zpbml0ZSh4KSAmJiBpc2Zpbml0ZSh5 KSAmJiAoeCA+IFJFQ0lQX1NRUlRfRVBTSUxPTl8xMDAgfHwgeSA+IFJFQ0lQ X1NRUlRfRVBTSUxPTl8xMDApKSB7DQogIAkJaWYgKGh1Z2UreCt5Pm9uZSkg eyAvKiByYWlzZSBpbmV4YWN0IGZsYWcgKi8NCiEgCQkJdyA9IGNsb2dfZm9y X2xhcmdlX3ZhbHVlcyh6KSArIE1fTE4yOw0KICAJCQlpZiAoc3kgPT0gMCkN CiEgCQkJCXJldHVybiAoY3BhY2tmKGNpbWFnZih3KSwgLWNyZWFsZih3KSkp Ow0KISAJCQlyZXR1cm4gKGNwYWNrZigtY2ltYWdmKHcpLCBjcmVhbGYodykp KTsNCiAgCQl9DQogIAl9DQotLS0gMjMzLDI0MiAtLS0tDQogIAlpZiAoaXNm aW5pdGUoeCkgJiYgaXNmaW5pdGUoeSkgJiYgKHggPiBSRUNJUF9TUVJUX0VQ U0lMT05fMTAwIHx8IHkgPiBSRUNJUF9TUVJUX0VQU0lMT05fMTAwKSkgew0K ICAJCWlmIChodWdlK3greT5vbmUpIHsgLyogcmFpc2UgaW5leGFjdCBmbGFn ICovDQohIAkJCXcgPSBjbG9nX2Zvcl9sYXJnZV92YWx1ZXMoeik7DQohIAkJ CXJ4ID0gZmFic2YoY2ltYWdmKHcpKTsNCiEgCQkJcnkgPSBjcmVhbGYodykg KyBNX0xOMjsNCiAgCQkJaWYgKHN5ID09IDApDQohIAkJCQlyeSA9IC1yeTsN CiEgCQkJcmV0dXJuIChjcGFja2YocngsIHJ5KSk7DQogIAkJfQ0KICAJfQ0K KioqKioqKioqKioqKioqDQoqKiogMjkwLDI5NCAqKioqDQogIAl9DQogIA0K ISAJaWYgKGF5ID4gMC41KkZMVF9NQVgpDQogIAkJcmV0dXJuIChjcGFja2Yo bG9nZihoeXBvdGYoeCAvIE1fRSwgeSAvIE1fRSkpICsgMSwgYXRhbjJmKHks IHgpKSk7DQogIA0KLS0tIDI5MiwyOTYgLS0tLQ0KICAJfQ0KICANCiEgCWlm IChheCA+IDAuNSpGTFRfTUFYKQ0KICAJCXJldHVybiAoY3BhY2tmKGxvZ2Yo aHlwb3RmKHggLyBNX0UsIHkgLyBNX0UpKSArIDEsIGF0YW4yZih5LCB4KSkp Ow0KICANCmRpZmYgLWMyIGNhdHJpZ2wuY34gY2F0cmlnbC5jDQoqKiogY2F0 cmlnbC5jfglTdW4gQXVnIDEyIDA2OjU0OjQ2IDIwMTINCi0tLSBjYXRyaWds LmMJTW9uIEF1ZyAxMyAxMjowODoyMSAyMDEyDQoqKioqKioqKioqKioqKioN CioqKiAxMTksMTIzICoqKioNCiAgCQlyZXR1cm47DQogIAl9DQohIAlpZiAo eSA8IE1JTl80VEhfUk9PVCkgew0KICAJCSpCX2lzX3VzYWJsZSA9IDA7DQog IAkJaWYgKChpbnQpeT09MCkgLyogcmFpc2UgaW5leGFjdCBmbGFnICovDQot LS0gMTE5LDEyMyAtLS0tDQogIAkJcmV0dXJuOw0KICAJfQ0KISAJaWYgKCFp c25hbih4KSAmJiB5IDwgTUlOXzRUSF9ST09UKSB7DQogIAkJKkJfaXNfdXNh YmxlID0gMDsNCiAgCQlpZiAoKGludCl5PT0wKSAvKiByYWlzZSBpbmV4YWN0 IGZsYWcgKi8NCioqKioqKioqKioqKioqKg0KKioqIDIwNywyMTQgKioqKg0K ICAJaWYgKGlzZmluaXRlKHgpICYmIGlzZmluaXRlKHkpICYmICh4ID4gUkVD SVBfU1FSVF9FUFNJTE9OXzEwMCB8fCB5ID4gUkVDSVBfU1FSVF9FUFNJTE9O XzEwMCkpIHsNCiAgCQlpZiAoaHVnZSt4K3k+b25lKSB7IC8qIHJhaXNlIGlu ZXhhY3QgZmxhZyAqLw0KISAJCQl3ID0gY2xvZ19mb3JfbGFyZ2VfdmFsdWVz KHopICsgTF9MTjI7DQogIAkJCWlmIChzeSA9PSAwKQ0KISAJCQkJcmV0dXJu IChjcGFja2woY2ltYWdsKHcpLCAtY3JlYWxsKHcpKSk7DQohIAkJCXJldHVy biAoY3BhY2tsKC1jaW1hZ2wodyksIGNyZWFsbCh3KSkpOw0KICAJCX0NCiAg CX0NCi0tLSAyMDcsMjE2IC0tLS0NCiAgCWlmIChpc2Zpbml0ZSh4KSAmJiBp c2Zpbml0ZSh5KSAmJiAoeCA+IFJFQ0lQX1NRUlRfRVBTSUxPTl8xMDAgfHwg eSA+IFJFQ0lQX1NRUlRfRVBTSUxPTl8xMDApKSB7DQogIAkJaWYgKGh1Z2Ur eCt5Pm9uZSkgeyAvKiByYWlzZSBpbmV4YWN0IGZsYWcgKi8NCiEgCQkJdyA9 IGNsb2dfZm9yX2xhcmdlX3ZhbHVlcyh6KTsNCiEgCQkJcnggPSBmYWJzbChj aW1hZ2wodykpOw0KISAJCQlyeSA9IGNyZWFsbCh3KSArIE1fTE4yOw0KICAJ CQlpZiAoc3kgPT0gMCkNCiEgCQkJCXJ5ID0gLXJ5Ow0KISAJCQlyZXR1cm4g KGNwYWNrbChyeCwgcnkpKTsNCiAgCQl9DQogIAl9DQoqKioqKioqKioqKioq KioNCioqKiAyNjQsMjY4ICoqKioNCiAgCX0NCiAgDQohIAlpZiAoYXkgPiAw LjUqTERCTF9NQVgpDQogIAkJcmV0dXJuIChjcGFja2wobG9nbChoeXBvdGwo eCAvIExfRSwgeSAvIExfRSkpICsgMSwgYXRhbjJsKHksIHgpKSk7DQogIA0K LS0tIDI2NiwyNzAgLS0tLQ0KICAJfQ0KICANCiEgCWlmIChheCA+IDAuNSpM REJMX01BWCkNCiAgCQlyZXR1cm4gKGNwYWNrbChsb2dsKGh5cG90bCh4IC8g TF9FLCB5IC8gTF9FKSkgKyAxLCBhdGFuMmwoeSwgeCkpKTsNCiAgDQo= --0-1116022701-1344877047=:3692--