Page 1 of 1

single/double precision - external dll

Posted: Wed Nov 10, 2010 11:04 am
by etam
I create some external functions and wanted to test if the used tools are coherent in number precision.
I wrote a simple model and I got some strange result, which I can't explain.

The model should show something like this:
input: 1.00000000000000000000
input: 12.00000000000000000000
input: 123.00000000000000000000
input: 1234.00000000000000000000
...

The strange thing that both with single and double precision, the problems occur in the same place:
input: 12345678.00000000000000000000
input: 123456789.00000000000000000000
input: 1234567920.00000000000000000000
input: 12345679361.00000000000000000000

I would have though that for double precision it would happen later.

I've checked as much as I could, but haven't find any answer.
Any idea?

My model:
-------------------------------------------------------
val=val dly * 10 + MODULO(Time, 10) ~~|
val ext=PREC(val) ~~|
val dly=DELAY FIXED (val,1,0) ~~|

FINAL TIME = 20 ~~|
INITIAL TIME = 0 ~~|
SAVEPER = TIME STEP ~~|
TIME STEP = 1 ~~|
-------------------------------------------------------

PREC is really simple:
-------------------------------------------------------
CFUNCTION int VEFCC vensim_external(VV *val, int nval, int funcid) {
...
case PREC_FUNC: rval = PREC(val[0].val);
...
}

double PREC(double x) {
char tmp_str[1024];
sprintf(tmp_str, "input: %1.20f", x);
vs_error_message(NOT_ERROR, tmp_str);
return x;
} // double PREC(double x)
-------------------------------------------------------

I use the Vensim version 5.10c.

Posted: Wed Nov 10, 2010 12:05 pm
by Administrator
I cannot understand what the problem is here.

The line
sprintf(tmp_str, "input: %1.20f", x);

prints a number with 20 decimal places. So the results you have look ok.

What exactly is the problem?

Posted: Wed Nov 10, 2010 12:11 pm
by etam
It's a precision test, which means the float/double differences should have shown up.
The results should be:
---- for float (single precision) - that's OK
...
1234567
12345678
123456792
1234567936
...

---- for double (double precision) - that's NOT OK in the Vensim model
1234567
12345678
123456789
1234567890
12345678901
123456789012
1234567890123
12345678901234
123456789012345
1234567890123456
12345678901234568
123456789012345700
...

Posted: Wed Nov 10, 2010 12:13 pm
by etam
More clear:

I don't understand, why are the model results
...
input: 12345678.00000000000000000000
input: 123456789.00000000000000000000
input: 1234567920.00000000000000000000
input: 12345679361.00000000000000000000
...
instead of
...
input: 12345678.00000000000000000000
input: 123456789.00000000000000000000
input: 1234567890.00000000000000000000
input: 12345678901.00000000000000000000
...
using Vensim double precision.

Posted: Wed Nov 10, 2010 3:52 pm
by tomfid
As I recall, models can run internally at dp, but results in .vdf files are still stored single precision. That might explain the output you're seeing.

Posted: Wed Nov 10, 2010 6:19 pm
by etam
Yes, I know that.

But calling an external function has nothing to do with vdf files, am I right?
That should be internal.

Also definitions (see COMPREAL) suggest that there are significant differences between single and double precision.

However, there is no difference in the example. How come?

Posted: Wed Nov 10, 2010 8:33 pm
by tomfid
If your test is performing an ordinary simulation, the information is coming from a .vdf, and therefore subject to the limitation. I'm not sure if that's also true if you're extracting output from a live synthesim run, but my guess is that it is.

Is there a special reason that you need double precision?

Tom

Posted: Wed Nov 10, 2010 8:35 pm
by tomfid
Wait a sec ... I wasn't paying close enough attention ... I assumed you were using the .dll, but actually you're writing an external function - so, you're right: vdfs are not involved.

Posted: Wed Nov 10, 2010 8:36 pm
by tomfid
My guess is that the issue has something to do with compiler headers or definitions, but I'm not sure - Bob would have to weigh in on that.

Tom

Posted: Wed Nov 10, 2010 9:50 pm
by etam
Thanks, I really don't know what the problem is.
One more thing, the val[0].val in the VEFCC vensim_external is a double variable, for sure (checked with sizeof), so the reason must be deeper inside I guess.

Posted: Thu Nov 11, 2010 12:42 pm
by bob@vensim.com
If you enter something like 12345678912 into a model equation that will be truncated to a single precision number, as that is the way it is stored internally within the model. To get more precision going in you will need to use a .cin file. This will be read as a simulation sets up and will be retained in its full precision for computations.

Posted: Thu Nov 11, 2010 12:45 pm
by etam
Yes I know that, but if you have a look at my model (first post), it's not the case.

-------------------------------------------------------
val=val dly * 10 + MODULO(Time, 10) ~~|
val dly=DELAY FIXED (val,1,0) ~~|
val ext=PREC(val) ~~|
-------------------------------------------------------

Posted: Thu Nov 11, 2010 12:49 pm
by etam
Maybe it is truncated within DELAY FIXED?

Posted: Thu Nov 11, 2010 1:03 pm
by etam
OK, that's the reason. DELAY FIXED truncates double values to single.
I checked with a different model, and that works.

Posted: Fri Nov 12, 2010 11:30 am
by bob@vensim.com
it is not DELAY FIXED - see the attached model and (in next message) .cin file - you should see difference go from -5 to 12.

Posted: Fri Nov 12, 2010 11:31 am
by bob@vensim.com
cin file

Posted: Fri Nov 12, 2010 11:47 am
by etam
You are right, DELAY FIXED does not truncate the values.

But I guess it looks them up from a storage (in case of data), which is truncated, and that's why the result.

Am I right?

First I thought for some reason that all time slots are in the memory, but to store and look them up is more logically.

Posted: Fri Nov 12, 2010 7:45 pm
by bob@vensim.com
Hi Etam,

I belatedly realized that my example was not correct, I need to delay the inputs, then take the difference. There results are different.

So you are right the DELAY... functions are truncating. That is a bug and will be fixed for the next release. It is also true that values brought in via GET XLS... were being truncated. That is by design, but will also be changed.

What will remain true is that stored values will be truncated.

Re: single/double precision - external dll

Posted: Tue Jan 17, 2017 6:31 am
by georgemacin
The decimal keyword denotes a 128-bit data type. Compared to floating-point types, the decimal type has a greater precision and a smaller range, which makes it suitable for financial and monetary calculations. Precision is the main difference where double is a double precision (64 bit) floating point data type and decimal is a 128-bit floating point data type.

Double - 64 bit (15-16 digits)

Decimal - 128 bit (28-29 significant digits)

So Decimals have much higher precision and are usually used within monetary (financial) applications that require a high degree of accuracy. But in performance wise Decimals are slower than double and float types. Double Types are probably the most normally used data type for real values, except handling money. In general, the double type is going to offer at least as great precision and definitely greater speed for arbitrary real numbers. More about...Double vs Decimal

George