#include <sys/time.h>
#include <stdio.h>
#include <stdint.h>
double getdoubletime() {
struct timeval t;
gettimeofday(&t, NULL);
return (double) t.tv_sec + ((double) t.tv_usec * 1e-6);
}
#include <math.h>
#include <stdlib.h>
#define N 65536
inline double min(double d1, double d2) { return d2 < d1 ? d2 : d1; }
inline double max(double d1, double d2) { return d2 > d1 ? d2 : d1; }
double fract_fast(double d) {
// Clamp d to values that are representable 64-bit integers.
// Any double-precision floating-point number outside of this range
// has no fractional part, so these calls to min / max will have
// no effect on the return value of this function.
d = min((double)(((int64_t)1)<<62), d);
d = max(-(double)(((int64_t)1)<<62), d);
// C / C++ define casts to integer as always being the round-toward-zero
// of the floating point number, regardless of rounding mode.
int64_t integral_part = (int64_t)d;
return d - (double)integral_part;
}
int main(int argc, char const *argv[]) {
size_t i;
double t0;
// generate some random floating-point numbers
double numbers[N];
double fractionals[N];
double meth1[N];
for (i=0; i<N; ++i) {
numbers
[i
] = rand() + rand() / (double)RAND_MAX
; }
// Throw in some edge cases for good measure
numbers[N - 1] *= -1;
numbers[N - 2] *= 1e30;
numbers[N - 3] *= -1e30;
// extract fractional part: method 1
t0 = getdoubletime();
double integral;
for (i=0; i<N; ++i) {
fractionals
[i
] = modf(numbers
[i
], &integral
); }
printf("method 1 took %lf seconds (using modf)\n", getdoubletime
() - t0
); for (i=0; i<N; ++i) {
meth1[i] = fractionals[i];
}
// extract fractional part: method 2
t0 = getdoubletime();
for (i=0; i<N; ++i) {
fractionals[i] = numbers[i] - (long)numbers[i];
}
printf("method 2 took %lf seconds (casting to long)\n", getdoubletime
() - t0
); for (i=0; i<N; ++i) {
if (meth1[i] != fractionals[i]) {
printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i
, numbers
[i
], meth1
[i
], fractionals
[i
]); if (i > 20) break;
}
}
// extract fractional part: method 3
t0 = getdoubletime();
for (i=0; i<N; ++i) {
fractionals[i] = fract_fast(numbers[i]);
}
printf("method 3 took %lf seconds (using min/max/casts/sub)\n", getdoubletime
() - t0
); for (i=0; i<N; ++i) {
if (meth1[i] != fractionals[i]) {
printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i
, numbers
[i
], meth1
[i
], fractionals
[i
]); if (i > 20) break;
}
}
// extract fractional part: method 4
t0 = getdoubletime();
for (i=0; i<N; ++i) {
fractionals
[i
] = numbers
[i
] - floor(numbers
[i
]); }
printf("method 4 took %lf seconds (using floor)\n", getdoubletime
() - t0
); for (i=0; i<N; ++i) {
if (meth1[i] != fractionals[i]) {
printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i
, numbers
[i
], meth1
[i
], fractionals
[i
]); if (i > 20) break;
}
}
// extract fractional part: method 5
t0 = getdoubletime();
for (i=0; i<N; ++i) {
fractionals[i] = fmod(numbers[i], 1.0);
}
printf("method 5 took %lf seconds (using fmod)\n", getdoubletime
() - t0
); for (i=0; i<N; ++i) {
if (meth1[i] != fractionals[i]) {
printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i
, numbers
[i
], meth1
[i
], fractionals
[i
]); if (i > 20) break;
}
}
// extract fractional part: method 6
t0 = getdoubletime();
for (i=0; i<N; ++i) {
fractionals[i] = remainder(numbers[i], 1.0);
}
printf("method 6 took %lf seconds (using remainder)\n", getdoubletime
() - t0
); for (i=0; i<N; ++i) {
if (meth1[i] != fractionals[i]) {
printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i
, numbers
[i
], meth1
[i
], fractionals
[i
]); if (i > 20) break;
}
}
return 0;
}
I2luY2x1ZGUgPHN5cy90aW1lLmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkaW50Lmg+Cgpkb3VibGUgZ2V0ZG91YmxldGltZSgpIHsKICAgIHN0cnVjdCB0aW1ldmFsIHQ7CiAgICBnZXR0aW1lb2ZkYXkoJnQsIE5VTEwpOwogICAgcmV0dXJuIChkb3VibGUpIHQudHZfc2VjICsgKChkb3VibGUpIHQudHZfdXNlYyAqIDFlLTYpOwp9CgojaW5jbHVkZSA8bWF0aC5oPgojaW5jbHVkZSA8c3RkbGliLmg+CgojZGVmaW5lIE4gNjU1MzYKCmlubGluZSBkb3VibGUgbWluKGRvdWJsZSBkMSwgZG91YmxlIGQyKSB7IHJldHVybiBkMiA8IGQxID8gZDIgOiBkMTsgfQppbmxpbmUgZG91YmxlIG1heChkb3VibGUgZDEsIGRvdWJsZSBkMikgeyByZXR1cm4gZDIgPiBkMSA/IGQyIDogZDE7IH0KCmRvdWJsZSBmcmFjdF9mYXN0KGRvdWJsZSBkKSB7CiAgLy8gQ2xhbXAgZCB0byB2YWx1ZXMgdGhhdCBhcmUgcmVwcmVzZW50YWJsZSA2NC1iaXQgaW50ZWdlcnMuCiAgLy8gQW55IGRvdWJsZS1wcmVjaXNpb24gZmxvYXRpbmctcG9pbnQgbnVtYmVyIG91dHNpZGUgb2YgdGhpcyByYW5nZQogIC8vIGhhcyBubyBmcmFjdGlvbmFsIHBhcnQsIHNvIHRoZXNlIGNhbGxzIHRvIG1pbiAvIG1heCB3aWxsIGhhdmUKICAvLyBubyBlZmZlY3Qgb24gdGhlIHJldHVybiB2YWx1ZSBvZiB0aGlzIGZ1bmN0aW9uLgogIGQgPSBtaW4oKGRvdWJsZSkoKChpbnQ2NF90KTEpPDw2MiksIGQpOwogIGQgPSBtYXgoLShkb3VibGUpKCgoaW50NjRfdCkxKTw8NjIpLCBkKTsKCiAgLy8gQyAvIEMrKyBkZWZpbmUgY2FzdHMgdG8gaW50ZWdlciBhcyBhbHdheXMgYmVpbmcgdGhlIHJvdW5kLXRvd2FyZC16ZXJvCiAgLy8gb2YgdGhlIGZsb2F0aW5nIHBvaW50IG51bWJlciwgcmVnYXJkbGVzcyBvZiByb3VuZGluZyBtb2RlLgogICAgaW50NjRfdCBpbnRlZ3JhbF9wYXJ0ID0gKGludDY0X3QpZDsKICAgIHJldHVybiBkIC0gKGRvdWJsZSlpbnRlZ3JhbF9wYXJ0Owp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciBjb25zdCAqYXJndltdKSB7CiAgICBzaXplX3QgaTsKICAgIGRvdWJsZSB0MDsKICAgIC8vIGdlbmVyYXRlIHNvbWUgcmFuZG9tIGZsb2F0aW5nLXBvaW50IG51bWJlcnMKICAgIGRvdWJsZSBudW1iZXJzW05dOwogICAgZG91YmxlIGZyYWN0aW9uYWxzW05dOwogICAgZG91YmxlIG1ldGgxW05dOwogICAgZm9yIChpPTA7IGk8TjsgKytpKSB7CiAgICAgICAgbnVtYmVyc1tpXSA9IHJhbmQoKSArIHJhbmQoKSAvIChkb3VibGUpUkFORF9NQVg7CiAgICB9CiAgICAvLyBUaHJvdyBpbiBzb21lIGVkZ2UgY2FzZXMgZm9yIGdvb2QgbWVhc3VyZQogICAgbnVtYmVyc1tOIC0gMV0gKj0gLTE7CiAgICBudW1iZXJzW04gLSAyXSAqPSAxZTMwOwogICAgbnVtYmVyc1tOIC0gM10gKj0gLTFlMzA7CgogICAgLy8gZXh0cmFjdCBmcmFjdGlvbmFsIHBhcnQ6IG1ldGhvZCAxCiAgICB0MCA9IGdldGRvdWJsZXRpbWUoKTsKICAgIGRvdWJsZSBpbnRlZ3JhbDsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICAgIGZyYWN0aW9uYWxzW2ldID0gbW9kZihudW1iZXJzW2ldLCAmaW50ZWdyYWwpOwogICAgfQogICAgcHJpbnRmKCJtZXRob2QgMSB0b29rICVsZiBzZWNvbmRzICh1c2luZyBtb2RmKVxuIiwgZ2V0ZG91YmxldGltZSgpIC0gdDApOwogICAgZm9yIChpPTA7IGk8TjsgKytpKSB7CiAgICAgIG1ldGgxW2ldID0gZnJhY3Rpb25hbHNbaV07CiAgICB9CgogICAgLy8gZXh0cmFjdCBmcmFjdGlvbmFsIHBhcnQ6IG1ldGhvZCAyCiAgICB0MCA9IGdldGRvdWJsZXRpbWUoKTsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICAgIGZyYWN0aW9uYWxzW2ldID0gbnVtYmVyc1tpXSAtIChsb25nKW51bWJlcnNbaV07CiAgICB9CiAgICBwcmludGYoIm1ldGhvZCAyIHRvb2sgJWxmIHNlY29uZHMgKGNhc3RpbmcgdG8gbG9uZylcbiIsIGdldGRvdWJsZXRpbWUoKSAtIHQwKTsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICBpZiAobWV0aDFbaV0gIT0gZnJhY3Rpb25hbHNbaV0pIHsKICAgICAgCXByaW50ZigiTWlzbWF0Y2ggYXQgJWQ6IGZyYWMoJS4xMmcpIGV4cGVjdGVkICUuMTJnLCBnb3QgJS4xMmdcbiIsIChpbnQpaSwgbnVtYmVyc1tpXSwgbWV0aDFbaV0sIGZyYWN0aW9uYWxzW2ldKTsKICAgICAgCWlmIChpID4gMjApIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgLy8gZXh0cmFjdCBmcmFjdGlvbmFsIHBhcnQ6IG1ldGhvZCAzCiAgICB0MCA9IGdldGRvdWJsZXRpbWUoKTsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICAgIGZyYWN0aW9uYWxzW2ldID0gZnJhY3RfZmFzdChudW1iZXJzW2ldKTsKICAgIH0KICAgIHByaW50ZigibWV0aG9kIDMgdG9vayAlbGYgc2Vjb25kcyAodXNpbmcgbWluL21heC9jYXN0cy9zdWIpXG4iLCBnZXRkb3VibGV0aW1lKCkgLSB0MCk7CiAgICBmb3IgKGk9MDsgaTxOOyArK2kpIHsKICAgICAgaWYgKG1ldGgxW2ldICE9IGZyYWN0aW9uYWxzW2ldKSB7CiAgICAgIAlwcmludGYoIk1pc21hdGNoIGF0ICVkOiBmcmFjKCUuMTJnKSBleHBlY3RlZCAlLjEyZywgZ290ICUuMTJnXG4iLCAoaW50KWksIG51bWJlcnNbaV0sIG1ldGgxW2ldLCBmcmFjdGlvbmFsc1tpXSk7CiAgICAgIAlpZiAoaSA+IDIwKSBicmVhazsKICAgICAgfQogICAgfQoKICAgIC8vIGV4dHJhY3QgZnJhY3Rpb25hbCBwYXJ0OiBtZXRob2QgNAogICAgdDAgPSBnZXRkb3VibGV0aW1lKCk7CiAgICBmb3IgKGk9MDsgaTxOOyArK2kpIHsKICAgICAgICBmcmFjdGlvbmFsc1tpXSA9IG51bWJlcnNbaV0gLSBmbG9vcihudW1iZXJzW2ldKTsKICAgIH0KICAgIHByaW50ZigibWV0aG9kIDQgdG9vayAlbGYgc2Vjb25kcyAodXNpbmcgZmxvb3IpXG4iLCBnZXRkb3VibGV0aW1lKCkgLSB0MCk7CiAgICBmb3IgKGk9MDsgaTxOOyArK2kpIHsKICAgICAgaWYgKG1ldGgxW2ldICE9IGZyYWN0aW9uYWxzW2ldKSB7CiAgICAgIAlwcmludGYoIk1pc21hdGNoIGF0ICVkOiBmcmFjKCUuMTJnKSBleHBlY3RlZCAlLjEyZywgZ290ICUuMTJnXG4iLCAoaW50KWksIG51bWJlcnNbaV0sIG1ldGgxW2ldLCBmcmFjdGlvbmFsc1tpXSk7CiAgICAgIAlpZiAoaSA+IDIwKSBicmVhazsKICAgICAgfQogICAgfQoKICAgIC8vIGV4dHJhY3QgZnJhY3Rpb25hbCBwYXJ0OiBtZXRob2QgNQogICAgdDAgPSBnZXRkb3VibGV0aW1lKCk7CiAgICBmb3IgKGk9MDsgaTxOOyArK2kpIHsKICAgICAgICBmcmFjdGlvbmFsc1tpXSA9IGZtb2QobnVtYmVyc1tpXSwgMS4wKTsKICAgIH0KICAgIHByaW50ZigibWV0aG9kIDUgdG9vayAlbGYgc2Vjb25kcyAodXNpbmcgZm1vZClcbiIsIGdldGRvdWJsZXRpbWUoKSAtIHQwKTsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICBpZiAobWV0aDFbaV0gIT0gZnJhY3Rpb25hbHNbaV0pIHsKICAgICAgCXByaW50ZigiTWlzbWF0Y2ggYXQgJWQ6IGZyYWMoJS4xMmcpIGV4cGVjdGVkICUuMTJnLCBnb3QgJS4xMmdcbiIsIChpbnQpaSwgbnVtYmVyc1tpXSwgbWV0aDFbaV0sIGZyYWN0aW9uYWxzW2ldKTsKICAgICAgCWlmIChpID4gMjApIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgLy8gZXh0cmFjdCBmcmFjdGlvbmFsIHBhcnQ6IG1ldGhvZCA2CiAgICB0MCA9IGdldGRvdWJsZXRpbWUoKTsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICAgIGZyYWN0aW9uYWxzW2ldID0gcmVtYWluZGVyKG51bWJlcnNbaV0sIDEuMCk7CiAgICB9CiAgICBwcmludGYoIm1ldGhvZCA2IHRvb2sgJWxmIHNlY29uZHMgKHVzaW5nIHJlbWFpbmRlcilcbiIsIGdldGRvdWJsZXRpbWUoKSAtIHQwKTsKICAgIGZvciAoaT0wOyBpPE47ICsraSkgewogICAgICBpZiAobWV0aDFbaV0gIT0gZnJhY3Rpb25hbHNbaV0pIHsKICAgICAgCXByaW50ZigiTWlzbWF0Y2ggYXQgJWQ6IGZyYWMoJS4xMmcpIGV4cGVjdGVkICUuMTJnLCBnb3QgJS4xMmdcbiIsIChpbnQpaSwgbnVtYmVyc1tpXSwgbWV0aDFbaV0sIGZyYWN0aW9uYWxzW2ldKTsKICAgICAgCWlmIChpID4gMjApIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIDA7Cn0K
method 1 took 0.000449 seconds (using modf)
method 2 took 0.000074 seconds (casting to long)
Mismatch at 65533: frac(-9.27517998277e+38) expected -0, got -9.27517998277e+38
method 3 took 0.000136 seconds (using min/max/casts/sub)
method 4 took 0.000175 seconds (using floor)
Mismatch at 65535: frac(-20429118.6606) expected -0.66055546701, got 0.33944453299
method 5 took 0.008163 seconds (using fmod)
method 6 took 0.001427 seconds (using remainder)
Mismatch at 1: frac(1681692777.8) expected 0.798439979553, got -0.201560020447
Mismatch at 3: frac(719885386.768) expected 0.768229603767, got -0.231770396233
Mismatch at 4: frac(596516649.554) expected 0.553969979286, got -0.446030020714
Mismatch at 5: frac(1025202362.63) expected 0.62887096405, got -0.37112903595
Mismatch at 6: frac(783368690.513) expected 0.513400912285, got -0.486599087715
Mismatch at 7: frac(2044897763.92) expected 0.91619515419, got -0.0838048458099
Mismatch at 8: frac(1365180540.72) expected 0.71729683876, got -0.28270316124
Mismatch at 9: frac(304089172.607) expected 0.6069688797, got -0.3930311203
Mismatch at 11: frac(294702567.804) expected 0.804176747799, got -0.195823252201
Mismatch at 15: frac(1101513929.84) expected 0.839112281799, got -0.160887718201
Mismatch at 17: frac(1369133069.52) expected 0.524287223816, got -0.475712776184
Mismatch at 18: frac(1059961393.97) expected 0.972774982452, got -0.0272250175476
Mismatch at 19: frac(628175011.771) expected 0.771357655525, got -0.228642344475
Mismatch at 20: frac(1131176229.77) expected 0.769913911819, got -0.230086088181
Mismatch at 21: frac(859484421.892) expected 0.89152944088, got -0.10847055912