Bug 691307

Summary: fix computation of fz_mul255
Product: MuPDF Reporter: riccardo <riccardo.lucchese>
Component: fitzAssignee: Tor Andersson <tor.andersson>
Status: RESOLVED FIXED    
Severity: enhancement CC: lev.bishop
Priority: P4    
Version: unspecified   
Hardware: PC   
OS: Linux   
Customer: Word Size: ---
Attachments: proof of correctness for the patched version
perf test (redirect output if you want to do any measures)
the actual patch

Description riccardo 2010-05-14 17:13:41 UTC
Created attachment 6288 [details]
proof of correctness for the patched version

Ideally fz_mul255(a,b) in mupdf/fitz/fitz_base.h should return round(float(a)*float(b)/255.) for all the couples (a,b) in the discrete set [0,255]x[0,255] (ie. the approximation with the lowest error energy over the set [0,255]x[0,255]). This is not the case for the current implementation which is returning a less then optimal value for half of the possible couples (a,b).

The attached patch fixes this. It also makes the multiplication around 20% faster on my machine.
Comment 1 riccardo 2010-05-14 17:14:22 UTC
Created attachment 6289 [details]
perf test (redirect output if you want to do any measures)
Comment 2 riccardo 2010-05-14 17:14:47 UTC
Created attachment 6290 [details]
the actual patch
Comment 3 Lev Bishop 2010-05-17 06:42:50 UTC
Note that the suggested patch does not round correctly for negative input. See bug 690631 for problems caused by fz_mul255 not treating negative numbers correctly.
Comment 4 riccardo 2010-05-17 12:11:14 UTC
If I understand correctly that the best thing to do is fixing the callers passing negative arguments to fz_mull255 one could deal whith interpolations by introducing something like:

#define fz_convex255(a,b,lambda)                                  \
                ({ unsigned int tmp;                              \
                   unsigned char _a = a;                          \
                   unsigned char _b = b;                          \
                   unsigned char _lambda = lambda;                \
                    tmp = _a*_lambda + _b*(255 ^ _lambda) + 0x80; \
                    tmp += tmp >> 8;                              \
                    tmp >> 8; })

[which has zero error-energy against round((float(a*lambda) + float(b*(255-lambda)))/255.) over the set [0,255]^3] and switching those call-sites to the new helper.
Comment 5 Tor Andersson 2010-05-20 22:04:38 UTC
I have applied Lev Bishop's earlier patches for this same problem.