2

I'm writting a C# library for interval arithmetic, and for that purpose I need to set floating-point operations rounding mode to Up and Down. I know that in C++ it can be achieved with a fesetround() function. Is there an equivalent in C#, or if there isn't, how can I achieve this the other way?

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
Buyuk
  • 1,094
  • 1
  • 8
  • 23
  • I think one can call C code easily from C#. You could simply call a C stub that sets the FPU rounding mode from your C# library. The rounding mode is set within the processor and will have an effect on all floating-point computations done by the CPU from that point onwards. – Pascal Cuoq Jun 16 '14 at 11:47
  • It would require to compile C++ code to a dll file, and then link it to my C# program? – Buyuk Jun 16 '14 at 11:54
  • 4
    Never tinker with the FPU control word in C#. It is the worst possible global variable you can imagine. With the standard misery that globals cause, your changes cannot last and will arbitrarily disappear. The internal exception handling code in the CLR resets it when it processes an exception. – Hans Passant Jun 16 '14 at 12:54
  • @Hans if you could give some hint on different way to set internal rounding mode (specifically for rounding decimal type). For example: `setroundmode( DOWNWARD ); var result = 2.0m/3.0m; // result expected: 0.66666666, actual result: 0.66666667` I would really appreciate any way, since just like you said, current approach is not a good fit for c# - in fact it doesn't work at all despite the fact that i'm certain i've created valid dll library with correct method implementation. – Buyuk Jun 18 '14 at 00:35
  • 2
    System.Decimal math is done is software, the FPU rounding mode does not affect it. There is no rounding control for it. – Hans Passant Jun 18 '14 at 06:33

2 Answers2

1

I followed Pascal Cuoq's advice and created a very simple - one function assembly. I post it in here if anyone else would ever experience such a problem.

Solution using my lib:

  1. Download dll file from: https://www.dropbox.com/s/o3vfxe4rpefhly7/RoundModeUtil.dll
  2. Add reference to the library in your project.
  3. Include using RoundModeUtils; line in project's code.
  4. Usage:

    static void RoundModeConfig::setround( int mode );
    
    // mode can be set to one of the following values: 
    static int RoundModeConfig::UPWARD
    static int RoundModeConfig::DOWNWARD
    static int RoundModeConfig::DEFAULT     // To nearest mode.
    static int RoundModeConfig::TOWARDZERO
    

Thanks Hans Passant for your advice,i should keep it in mind. Thanks everybody for help, hope someone will find my dll useful :)

Buyuk
  • 1,094
  • 1
  • 8
  • 23
1

For windows:

/// <remarks>
/// https://en.cppreference.com/w/cpp/numeric/fenv/FE_round
/// </remarks>
public enum RoundMode
{
    /// <summary>
    /// Rounding towards nearest representable value.
    /// </summary>
    FE_TONEAREST = 0x00000000,

    /// <summary>
    /// Rounding towards negative infinity.
    /// </summary>
    FE_DOWNWARD = 0x00000100,

    /// <summary>
    /// Rounding towards positive infinity.
    /// </summary>
    FE_UPWARD = 0x00000200,

    /// <summary>
    /// Rounding towards zero.
    /// </summary>
    FE_TOWARDZERO = 0x00000300,
}


public static class ExternMethods
{
    [DllImport("ucrtbase.dll", EntryPoint = "fegetround", CallingConvention = CallingConvention.Cdecl)]
    public static extern RoundMode GetRound();

    [DllImport("ucrtbase.dll", EntryPoint = "fesetround", CallingConvention = CallingConvention.Cdecl)]
    public static extern int SetRound(RoundMode roundingMode);
}