4

I am interessted in the actual Math.Ceiling function, how the algorithm behind this function is implemented in the .net framework. I've checked the function Math.Ceiling with a decompiler in mscorlib.dll , - but it seems like it is implemented by native code :

enter image description here

How can I find out how the algorithm the Ceiling function uses looks like?

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
yq8
  • 145
  • 1
  • 10
  • 3
    It is an `InternalCall` method. That means it is in CLR written with C++. If you _really_ wanna see it, best option is to get a job at Microsoft CLR Team. – Soner Gönül Jan 21 '16 at 15:17
  • 2
    As an aside, you can also check the [Reference Source](http://referencesource.microsoft.com/#mscorlib/system/math.cs,1841a5ce24ed9fb3) to see the code. Although in this case it gives you nothing more than what you already have. – Matt Burland Jan 21 '16 at 15:20
  • 1
    Possible duplicate of [How is Math.Pow() implemented in .NET Framework?](http://stackoverflow.com/questions/8870442/how-is-math-pow-implemented-in-net-framework) – Thomas Ayoub Jan 21 '16 at 15:35
  • 1
    This will undoubtedly be implementation specific. There are probably FPUs out there for which this is a single op. – John Sensebe Jan 21 '16 at 15:36
  • @Thomas I would say so; otherwise what is to stop someone asking the same question for every method in the class? – Meirion Hughes Jan 21 '16 at 15:52

1 Answers1

4

Yes for double numbers it's actually external code:

[System.Security.SecuritySafeCritical]  // auto-generated
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern double Ceiling(double a); 

That means that the method is actually implemented in the CLR, written in C++. The lookup table is located in clr/src/vm/ecalllist.h. The section that's relevant to Math.Ceiling() looks like this:

FCFuncStart(gMathFuncs)
  ...
  FCFuncElement("Log10", COMDouble::Log10)
  FCFuncElement("Ceiling", COMDouble::Ceil)
  FCFuncElement("SplitFractionDouble", COMDouble::ModFDouble)
  ...

CLR implementation calls native function:

FCIMPL1_V(double, COMDouble::Ceil, double d) 
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    return (double) ceil(d);
FCIMPLEND

Here is an implementation from <cmath>:

#include <cmath>
#include <cfenv>
#pragma STDC FENV_ACCESS ON
double ceil(double x)
{
    double result;
    int save_round = std::fegetround();
    std::fesetround(FE_UPWARD);
    result = std::rint(x); // or std::nearbyint 
    std::fesetround(save_round);
    return result;
}

See also Hans answer for more details.

Community
  • 1
  • 1
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43