## digitalmars.D.learn - CTFE fmod ?

• userABCabc123 (34/34) Nov 20 2015 Does someone have a good CTFE fmod() function ? The problem is
• rumbu (33/38) Nov 20 2015 Not thoroughly tested and only works for doubles, but this must
• userABCabc123 (2/9) Nov 20 2015 Thx, it works, easy to adapt to float.
userABCabc123 <userABCabc123 abc.ba> writes:
```Does someone have a good CTFE fmod() function ? The problem is
that std.math.fmod() is itself not available at CT, neither do
floor() or similar functions necessary to get the quotient when
the input value is two times over/under the bounds.

Currently I have this one...

---
auto warp(T)(T x, T min, T max)
{
if (x > max)
{
T rng = max - min;
while (x > max + rng)
x -= rng * 2;
if (x > max)
x -= rng;
}
else if (x < min)
{
T rng = max - min;
while (x < min - rng)
x += rng * 2;
if (x < min)
x += rng;
}
return x;
}
---

...but it fails to compile with certain float values. This
example will consume a lot of memory ( I guess it's the while()
loop in the CTFE VM who's responsible):

---
static assert(warp(2357136044, -5f, 5f).approxEqual(-1f));
---

Any suggestion ? Or maybe this is a limit ?
```
Nov 20 2015
rumbu <rumbu rumbu.ro> writes:
```On Friday, 20 November 2015 at 11:16:13 UTC, userABCabc123 wrote:
Does someone have a good CTFE fmod() function ? The problem is
that std.math.fmod() is itself not available at CT, neither do
floor() or similar functions necessary to get the quotient when
the input value is two times over/under the bounds.

Any suggestion ? Or maybe this is a limit ?

Not thoroughly tested and only works for doubles, but this must
do the trick.

double ctfe_trunc(double x)  trusted pure nothrow  nogc
{
ulong bits = *cast(ulong*)(&x);
auto sign = bits & 0x8000000000000000;
long exponent = (bits >> 52) & 0x7FF;
auto mantissa = (bits & 0xFFFFFFFFFFFFF);

if (exponent == 0 && mantissa == 0)
return 0.0;
else if (exponent == 0x7FF && mantissa == 0)
return sign ? -double.infinity : double.infinity;
else if (exponent == 0x7FF)
return double.nan;

exponent -= 1023;
auto target = 52 - exponent;
if (target >= 0 && target <= 51)
{
auto msb = mantissa & (1UL << target);
auto lsb = mantissa & ~((1UL << target) - 1);
bits = sign | ((exponent + 1023)) << 52 | lsb;
mantissa += msb;
return *cast(double*)&bits;
}
else
return sign ? -0.0 : 0.0;
}

double ctfe_fmod(double x, double y)  safe pure nothrow  nogc
{
return x - ctfe_trunc(x / y) * y;
}
```
Nov 20 2015
userABCabc123 <userABCabc123 ab.ba.ab> writes:
```On Friday, 20 November 2015 at 13:44:11 UTC, rumbu wrote:
On Friday, 20 November 2015 at 11:16:13 UTC, userABCabc123
wrote:
[...]

[...]

Not thoroughly tested and only works for doubles, but this must
do the trick.

[...]

Thx, it works, easy to adapt to float.
```
Nov 20 2015