One of our beta test customers discovered a small incompatibility for the mod function. Mod is not only defined for integers, but should be valid also for float numbers.

f := mod(2.6, 0.5) -> VO: 0.1 X#: Exception

f := mod(2.6, 2) -> VO: 0.6 X#: 0

It makes really sense using floats in the mod function, if you have to distribute articles quantities into packages:

- over all quantity of 2.6 liters to be shipped.

- Packages of 0.5 liters

-> 5 packages of 0.5 liters can be sent plus a remainder of 0.1 liters.

Arne

## Small incompatibility with mod operator/function

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

Hi Arne,

Mod() is indeed defined also for floating point operations. I tried your samples and they seem to work fine, but maybe it is a combination of compiler options that causes the problem. Can you please post a full sample project reproducing this problem, so we can have a look into it and fix it?

Mod() is indeed defined also for floating point operations. I tried your samples and they seem to work fine, but maybe it is a combination of compiler options that causes the problem. Can you please post a full sample project reproducing this problem, so we can have a look into it and fix it?

Chris Pyrgas

XSharp Development Team test

chris(at)xsharp.eu

XSharp Development Team test

chris(at)xsharp.eu

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

Hi Chris,

thank you for answering so quickly. I have sent you an example via email. Probably it depends on compiler settings and variable types used.

Arne

thank you for answering so quickly. I have sent you an example via email. Probably it depends on compiler settings and variable types used.

Arne

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

Chris has already found the reason: Usage of usuals as arguments. As a workaround I can help the compiler with casting types: f := Mod(FLOAT(u), fn) with u as usual, fn as float. Having floats or ints as arguments everything works correctly.

Arne

Arne

### Small incompatibility with mod operator/function

Hi Arne,

Unfortunately it's even more complicated than that, see https://github.com/X-Sharp/XSharpPublic/issues/571 for some more cases.

The problem is that we tried to make the Mod() function more efficient than in VO, by providing overloads for different parameter types, but this means that now it's up to the compiler to decide at compile time how to handle the expression, without knowing in advance what the params will represent at runtime.

We could remove the overloads and provide a single Mod() function with USUALs as in VO and make it 100% VO compatible, but this would require a full rebuild of all 3rd party libraries, which is probably better to avoid for now, since the next build will already contain several changes.

Is the workaround with the FLOAT() conversion sufficient enough for you for now?

Unfortunately it's even more complicated than that, see https://github.com/X-Sharp/XSharpPublic/issues/571 for some more cases.

The problem is that we tried to make the Mod() function more efficient than in VO, by providing overloads for different parameter types, but this means that now it's up to the compiler to decide at compile time how to handle the expression, without knowing in advance what the params will represent at runtime.

We could remove the overloads and provide a single Mod() function with USUALs as in VO and make it 100% VO compatible, but this would require a full rebuild of all 3rd party libraries, which is probably better to avoid for now, since the next build will already contain several changes.

Is the workaround with the FLOAT() conversion sufficient enough for you for now?

Chris Pyrgas

XSharp Development Team test

chris(at)xsharp.eu

XSharp Development Team test

chris(at)xsharp.eu

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

Hi Chris,

I think that the workaround is ok for us. I will try it the next days. There shouldn't be many occurrences like this in our code. In any case it seems to be an ugly solution that has been used here.

Arne

I think that the workaround is ok for us. I will try it the next days. There shouldn't be many occurrences like this in our code. In any case it seems to be an ugly solution that has been used here.

Arne

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

I am now changing our occurrences with float or usual parameters.

It is interesting how many effects someone can find out in long running programs.

The result for mod(2, 0.2) is not 0 as someone could imagine. It is 0.2!

But this result in X# is equal in C#, VO, Python.

mod(20.0, 2.0) gives 0 in all these programs.

Arne

It is interesting how many effects someone can find out in long running programs.

The result for mod(2, 0.2) is not 0 as someone could imagine. It is 0.2!

But this result in X# is equal in C#, VO, Python.

mod(20.0, 2.0) gives 0 in all these programs.

Arne

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

Here an answer can be found:

https://www.stata.com/support/faqs/data ... -function/

https://www.stata.com/support/faqs/data ... -function/

### Small incompatibility with mod operator/function

Arne,

It is even worse than that in VO:

The VO runtime uses inline assembler and the Numeric coprocessor for calculations.

What happens is this:

- The input for the Mod() function are 2 64 bit floating point numbers (REAL8)

- In the inline assembler these 2 numbers are loaded in the floating point registers in the coprocessor. These registers are not 64 bits but 80 bits, so a conversion takes place (this is done with the FLD QWORD PTR instruction)

- The modulo operation is performed on 2 80 bits numbers and the result is a new 80 bits number

- The result is converted back from 80 bits to 64 bits (this is done with the FSTP QWORD PTR instruction)

So there are "rounding errors" on 3 spots:

- Input 2 * 64 -> 80 bits

- Calculation -> modulo on fractional numbers is never 100% accurate

- Output 80 -> 64 bits

This makes you wonder how our apps were running....

Robert

It is even worse than that in VO:

The VO runtime uses inline assembler and the Numeric coprocessor for calculations.

What happens is this:

- The input for the Mod() function are 2 64 bit floating point numbers (REAL8)

- In the inline assembler these 2 numbers are loaded in the floating point registers in the coprocessor. These registers are not 64 bits but 80 bits, so a conversion takes place (this is done with the FLD QWORD PTR instruction)

- The modulo operation is performed on 2 80 bits numbers and the result is a new 80 bits number

- The result is converted back from 80 bits to 64 bits (this is done with the FSTP QWORD PTR instruction)

So there are "rounding errors" on 3 spots:

- Input 2 * 64 -> 80 bits

- Calculation -> modulo on fractional numbers is never 100% accurate

- Output 80 -> 64 bits

This makes you wonder how our apps were running....

Robert

XSharp Development Team

The Netherlands

robert@xsharp.eu

The Netherlands

robert@xsharp.eu

- ArneOrtlinghaus
**Posts:**385**Joined:**Tue Nov 10, 2015 7:48 am**Location:**Italy

### Small incompatibility with mod operator/function

This is interesting. In my tests I saw that VO sometimes has a higher precision than Dotnet with double/real8, about 3 decimals. This should be due to the use of the 80 bit FPU.

I believe that it needs always quite a lot of work to make business applications work correctly with floating point values . This especially if a database is in between with its own rounding behaviors. Probably converting to the Dotnet type DECIMAL will help in some cases. (decimal)2.0 % (decimal)0.2 gives 0.0.

I believe that it needs always quite a lot of work to make business applications work correctly with floating point values . This especially if a database is in between with its own rounding behaviors. Probably converting to the Dotnet type DECIMAL will help in some cases. (decimal)2.0 % (decimal)0.2 gives 0.0.