Hello Kern,
2013/2/9 Kern Sibbald <kern.sibb...@baculasystems.com>
> Hello Radoslaw,
>
> Originally we did not use floating point output, because it was very
> badly broken -- it seg faulted all the time. Somewhat later, I enabled
> it so we could use in a few places where we needed decimal numbers.
>
> The routine could well be broken, I simply worked on it until it seemed
> to work correctly, but I did not try out all cases. One thing to check
> and to be careful about is whether you are giving it a 32 bit value or a
> 64 bit value. Our conventions do not at all flow the stupid system
> dependent conventions of glibc. I may have used only 64 bit floating
> numbers.
>
I understand the history and legacy of the code. I proposed a simple patch
which fix this particular incorrectness. You can use it if you want.
>
> I can see your patch, and I can understand the logic of the
> original, but I don't understand why the original is wrong or why
> yours works.
>
>
The logic of the original code (the same logic for conversion integer and
fractional part of the floating point number) is working only for integer
part of the conversion and is not working for the fractional one because
leading zeros are obsolete for integer part (and original logic simply
ignores them) and very, very important for the fractional one = required
precision.
For example, a floating point number: 1.05 with precision 2 (max=2) is
splited into two parts: intpart = 1 and fractional one fracpart = 5 in
below code:
691: intpart = (int64_t)ufvalue;
(...)
700: /* We "cheat" by converting the fractional part to integer by
701: * multiplying by a factor of 10
702: */
703: fracpart = round((pow10(max)) * (ufvalue - intpart));
With above variables the main conversion loop:
727: /* Convert fractional part */
728: cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef";
729: do {
730: fconvert[fplace++] = cvt_str[fracpart % 10];
above stores '5' in fconvert [0] in first loop, which is ok
731: fracpart = (fracpart / 10);
fracpart is set to zero (int)(5/10) = 0
732: } while (fracpart && (fplace < (int)sizeof(fconvert)));
and above loop condition (fracpart) forces loop to finish - we had only one
conversion loop but requirement was for two...
My patch forces two loop runs which allow to required precision and leading
zero to hit the conversion buffer.
Our variables after conversion loop in original code:
fracpart = 0
fconvert[] = "5"
fplace = 1
max = 2
Variables after conversion loop in patched code:
fracpart = 0
fconvert[] = "50"
fplace = 2
max = 2
Now the following loop is filling output buffer for fractional part of the
conversion:
841: /*
842: * Decimal point. This should probably use locale to find the
correct
843: * char to print out.
844: */
845: if (max > 0) {
846: outch('.');
847: while (fplace > 0) {
848: fplace--;
849: outch(fconvert[fplace]);
850: }
851: }
which add string: ".5" to the output in original code. Full output will be
then: "1.5" which is incorrect because our fp number was: 1.05. With my
patch the above loop will produce a string ".05" and full output will be
then "1.05", which is correct and expected.
I hope this explains the original code logic and my patch.
best regards
--
Radosław Korzeniewski
rados...@korzeniewski.net
------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
Bacula-devel mailing list
Bacula-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-devel