Hi John,
On 30/11/10 09:35, John LeMoyne Castle wrote:
Currency is presently implemented with a 64bit struct of 2 Int32s and the
math is done by the tools/bigint class.
The attached patches replace the code to implement the Currency type with an
ISO C99 compiler supported 64 bit integer.
Absolutely, using 64bit integer types makes sense
In fact, the 64 bit int was already a member of the Sbx core data union.
[...]
http://nabble.documentfoundation.org/file/n1991648/0001-Basic-Currency-64bit-impl-fixes-i31001-to--libs-core.patch.tar.gz
0001-Basic-Currency-64bit-impl-fixes-i31001-to--libs-core.patch.tar.gz
This is integrated now in the feature branch feature/currency-64bit, in
the main I am really happy with this patch, here is a summary of things
I changed/modified etc.
First off the patch didn't build for me, at a wild guess I'd say maybe
you built this on a 32 bit system ( as the error seemed 64 bit related..
but I am not completely sure :-) ) error was..
../../inc/basic/sbxvar.hxx:92:5: error:
'SbxValues::SbxValues(sal_Int64)' cannot be overloaded
./../inc/basic/sbxvar.hxx:87:5: error: with 'SbxValues::SbxValues(long
int)'
dmake: Error code 1, while making '../../unxlngx6.pro/obj/sbintern.obj'
in anycase I removed the associated SbxValues constructor as it seemed
to enforce SbxValues::SbxValues(sal_Int64) would set the type of
SbxValues as SbxCURRENCY. I don't think it's a good idea to enforce
that, sal_Int64 just happens to the the data type we use for the
SbxCURRENCY type, it isn't indicative of the type itself.
I reverted the change below
-#define SbxMININT (-32768)
+#define SbxMININT (-32767)
I thought perhaps this wasn't intentional until I saw similar in the
test document, did you have a specific reason for changing that, imo we
can't change that as it is a hard limit. ( btw I changed it in both the
test document and the code and see no difference in the generated results )
I removed various comments that looked I guess like internal notes to
yourself, please have a look and ensure that I didn't remove something
you really want to keep. As an example ( from basic/inc/basic/sbxdef.hxx )
-#define SBX_MAXINDEX 0x3FF0
-#define SBX_MAXINDEX32 SbxMAXLNG
+// ?can we remove this ~16k limit on array index/size?
+#define SBX_MAXINDEX 0x3FF0
+#define SBX_MAXINDEX32 SbxMAXLNG
+
as an aside of course Arrays and such are no longer limited ( afaik ) by
16bit I guess we probably could get rid of the many side by side 16 and
32 bit variants of some method ( see Get32 & Get methods in SbxArray )
But that would be another task ( and I am not really sure the effort to
do that is worth it with so many other problems to look at )
in sbxToUnoValueImpl ( convert to uno without known target class ) in
basic/source/classes/sbunoobj.cxx previously an Double or Float basic
value ( within the range of an int ) was transfered as a the smallest
type e.g. sal_Int8, sal_Int16 or sal_Int32 values greater were
transferred as Float or Double
* there is a bit possibility that we could break existing code, care
needed here I thing ( transferring the value as sal_Int64 might seem
natural but hyper seems to be rarely used in uno interfaces ) not sure
about this, I am tempted to just let things break ( 'cause they seem
wrong in the first place ) Otoh the comments in the code do suggest
converting to int is intentional. ( erring on the side of caution it's
#ifdefed out ( with #if MAYBEFUTURE ) at the moment )
I see you have wiped the following types SbxLONG64 & SbxULONG64 from the
face of the earth ;-) I can't see that these are used anywhere and I
would guess they are handled probably in the binary filter code only. So
I hope this change is ok too.
in basic/source/runtime/methods1.cxx you have added incomplete
read/write support for types SbxSALINT64 & SbxSALUINT64, lets not add
support to persist a new type incompletely ( to easy to forget about )
so I've #ifdefed it out ( with #if IMPLEMENTATION_READY )
I fixed a couple of identical treatment of SALxINT64 & SbxCURRENCY types
e.g. sbxbyte ( there were others too ) these break things like
dim a as currency
dim b as byte:w
a = 1
b = a '<- overflows here ( clearly incorrect )
other types are similarly affected
similar to the above there I also fixed some mismatch with the Get/Put (
maybe some of this was pre-existing, I wouldn't be suprised )
I re-added some checks for removed limit checks ( actually I hope that I
didn't make things worse here as all this similar methods started making
my head spin, it's quite possible I screwed something up )
changed signature of ImpPutCurrency( sal_Int64& n ) 'tis a bad idea
'cause the incoming could be unexpectedly changed ( I realise this is an
oversight due to the fact that previously this method had an object
passed in the signature ) perhaps I am being paranoid... but anyway I
changed it
fixed some missing breaks in various case statements, e.g. at there was
a break removed from sbxdec ( within case SbxBYREF | SbxSINGLE ) was it
a intentional? ( I added back in the break but maybe I was wrong )
and also in sbxlng SbxSALINT64, SbxSALUINT64 missing breaks ( I think
there were some others too )
I rewrote the ImpCurrencyToString, I took note of your suggestions re.
optimizations whilst trying to point you to some existing functionality
available from the String classes as its better to avoid generating even
more number to string code. Somewhere between trying to write down some
explanations and suggestions I'm afraid I found myself actually
rewriting this and then I found mistakes in my 'new' implementation...
couldn't help myself. Anyway hopefully some of the code there shows some
other possibilities to achieve the same thing reusing some of the
existing LO classes. ( I have no doubt that there probably is some bugs
in my implementation too ). Additionally I am still very uncertain about
ImpStringToCurrency() changes to use Locale specific separators. Also
not sure about the local seperator logic, the heuristics used I think
might give an undesired result under some circumstances. I don't want to
rule it out but for the moment I would feel happier with the locale
specific part being #ifdefed out ( so I did that with some more #if
MAYBEFUTURE blocks ).
SbxValue::LoadData & SbxValue::SaveData, we need to ensure that a
Currency val written from the old Currency implementation can be read
with the new implementation and vice-versa ( looking at the code it
seems that it should work ). Hmmm but thinking about this more I really
don't see why this is necessary, I can't think of why a types value
would be saved with this this code, I wonder is it really dead code,
note the Load/Save methods are definitely used ( one usage I know about
is when saving password protected macros ) but... in this case it is the
pcode that is saved and I can't see why/where a variables value would be
saved. It's also possible the automation framework might use that ( but
that shouldn't be a problem either). So a) need to confirm the
read/write the old/new Currency type ( similarly the transfer of
oleautomation::Currency ) b) would be great to investigate further to
see what can be removed from those LoadData/SaveData methods.
It would be great if you could look over my changes and see if they are
ok, if you are happy with the change and if we can satisfy ourselves
that LoadData/SaveData item above is not an issue then we could probably
commit this to the master, then we can look further into some of the
ifdefed out stuff, how does that sound?
thanks again for the great patch and really cool test document
Noel
http://nabble.documentfoundation.org/file/n1991648/0001-Basic-Currency-type-native-64bit-implemen-components.patch
0001-Basic-Currency-type-native-64bit-implemen-components.patch
http://nabble.documentfoundation.org/file/n1991648/CurTestODS.ods.tar.gz
CurTestODS.ods.tar.gz
The attached CurTestODS.ods spreadsheet Basic program CurTestRunAll
demonstrates the errors from the old implementation:
-- flagrantly wrong values from string inputs
-- hugely wrong values from MDAS calculation
(where flagrantly, hugely == 10+ orders of magnitude off)
-- no-op (returning one of the operands instead of doing the operation)
-- incorrect overflow from operations on bad string input values
-- different errors and error rates on different platforms (in LibO Beta
3 on Ubuntu10.04 and WinVista)
The errors appear to start when results reach ~2.15e5 [(2^31-1)/10,000].
They continue up through the Currency upper limit of ~1e15.
The errors affect all of the basic MDAS (*/+-) math operations mostly(?) add
and subtract.
I didn't troubleshoot the errors thoroughly because the offending code was
either:
ripped out and replaced with simple C++ operations on the compiler supported
64 bit int, or
removed by rework of the Compute, Get and Put routines in sbx/*.
I think probably there was maybe a single point of failure here that
rippled through, certainly
The test program is CurTestODS.ods :: Standard :: CurTestRunAll
CurTestRunAll tests number pairs from the CurTestMeta sheet by:
-2x- reading the numbers in as strings or doubles
-4x- performing all MDAS (*/+-) operations
-16x- for all Basic operand type combinations of integer(16b), long (32b),
double (64b) and currency
for 128 tests on each number pair each test producing a Currency type
result.
Expected values are calculated by a parallel calculation in doubles to
produce an expected Currency type result.
Anticipated Basic run-time errors (overflow and div by zero) are identified
and passed.
Unexpected BRT errors are counted and output as errors.
All of the PostFix result sheets show a great reduction in the number of
errors over Beta3 when the new implementation is used.
The 4 remaining "errors" in the Demo result set show both the strength and
the weakness of the fixed point Currency type relative to the double
precision floating point type. These type differences pre-exist by
definition and will not go away in any implementation. Where more
fractional digits are needed the Double is more accurate, but when more
significant digits are needed the Currency type is more accurate.
What else it does:
The fix needed to include corrections to the
currency-get-value-from-string-literal because it was a source of bad
values. Users have requested in OOo issues to get the ability to use string
literals in their Locale format as set in the options. The new string
getter relaxes the requirement that string literal be in en-US format (i.e.
"1,000,000.00") - it will now accept "1.000.000,00" if the Locale allows it
while always accepting the Basic standard en-US format. The getter will
also always accept (always ignore) spaces within a number string so "1 000
000.00 00" is accepted. The Locale read was lifted from another of the
Currency string input functions. If this needs rework or reversion let me
know.
I thought this would be easy - and it was easy and fun - it was just a real
Big Easy...
All contributions licensed per TDF standard: MPL 1.1 / GPLv3+ / LGPLv3+
--LeMoyne (JLCastle)
Context
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.