#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
char *fmtp04f(char *buf, char *lim, double d) {
// if there's no space at all don't bother
if(buf==lim) return buf;
// 10 characters in maximum 32 bit integer, one for the dot,
// one for the terminating NUL in debug prints
char b[12];
// current position in the buffer
char *bp = b;
// scale and round
int32_t i = lrint(d * 10000.);
// write sign and fix i sign
// (we do have at least one character available in buf)
if(signbit(d)) {
*buf++='-';
i = -i;
} else {
*buf++='+';
}
// *always* write down the last 4 digits, even if they are zeroes
// (they'll become the 4 digits after the decimal dot)
for(; bp!=b+4; ) {
*bp++ = '0' + i%10;
i/=10;
}
*bp++='.';
// write down the remaining digits, writing at least one
do {
*bp++ = '0' + i%10;
i/=10;
} while(i != 0);
// bp is at the character after the last, step back
--bp;
// data is now into b *in reversed order*;
// reverse-copy it into the user-provided buffer
while(buf!=lim) {
*buf++ = *bp;
// check before decrementing, as a pointer to one-before-first
// is not allowed in C
if(bp == b) break;
--bp;
}
if(buf!=lim) *buf=0; // "regular" case: terminate *after*
else lim[-1]=0; // bad case: truncate
return buf;
}
void doformat(char *buf, char *lim, double a, double b) {
if(buf==lim) return; // cannot do anything
*buf++='{';
if(buf==lim) goto end;
buf = fmtp04f(buf, lim, a);
if(buf==lim) return; // already terminated by fmtp04f
*buf++=',';
if(buf==lim) goto end;
buf = fmtp04f(buf, lim, b);
if(buf==lim) return; // idem
*buf++='}';
if(buf==lim) goto end;
*buf++=0;
end:
lim[-1]=0; // always terminate
}
int main() {
double test_cases[] = {0., 1., 100., 1.2345678, 12345.678, 3.1415, 9.115251, 99999.1234, 0.};
char buf1[22];
char buf2[256];
char *buf2r = buf2+128;
for(int i=0, n=(sizeof(test_cases)/sizeof(*test_cases))-1; i<n; ++i) {
for(int sgn = 0; sgn<4; ++sgn) {
memset(buf2
, 255, sizeof(buf2
)); double a = test_cases[i];
if(sgn&1) a = -a;
double b = test_cases[i+1];
if(sgn&2) b = -b;
snprintf(buf1
, sizeof(buf1
), "{%+0.4f,%+0.4f}", a
, b
); doformat(buf2r, buf2r+22, a, b);
printf("buf1 [%s] != buf2r [%s]\n", buf1
, buf2r
); }
for(const char *p=buf2; p<buf2r; ++p) {
if((unsigned char)(*p)!=255) {
printf("unexpected %d at %d\n", *p
, (int)(p
-buf2
)); }
}
for(const char *p=buf2r+22; p<buf2 + sizeof(buf2); ++p) {
if((unsigned char)(*p)!=255) {
printf("unexpected %d at %d\n", *p
, (int)(p
-buf2
)); }
}
}
}
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxtYXRoLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGludC5oPgoKY2hhciAqZm10cDA0ZihjaGFyICpidWYsIGNoYXIgKmxpbSwgZG91YmxlIGQpIHsKICAgIC8vIGlmIHRoZXJlJ3Mgbm8gc3BhY2UgYXQgYWxsIGRvbid0IGJvdGhlcgogICAgaWYoYnVmPT1saW0pIHJldHVybiBidWY7CiAgICAvLyAxMCBjaGFyYWN0ZXJzIGluIG1heGltdW0gMzIgYml0IGludGVnZXIsIG9uZSBmb3IgdGhlIGRvdCwKICAgIC8vIG9uZSBmb3IgdGhlIHRlcm1pbmF0aW5nIE5VTCBpbiBkZWJ1ZyBwcmludHMKICAgIGNoYXIgYlsxMl07CiAgICAvLyBjdXJyZW50IHBvc2l0aW9uIGluIHRoZSBidWZmZXIKICAgIGNoYXIgKmJwID0gYjsKICAgIC8vIHNjYWxlIGFuZCByb3VuZAogICAgaW50MzJfdCBpID0gbHJpbnQoZCAqIDEwMDAwLik7CiAgICAvLyB3cml0ZSBzaWduIGFuZCBmaXggaSBzaWduCiAgICAvLyAod2UgZG8gaGF2ZSBhdCBsZWFzdCBvbmUgY2hhcmFjdGVyIGF2YWlsYWJsZSBpbiBidWYpCiAgICBpZihzaWduYml0KGQpKSB7CiAgICAgICAgKmJ1ZisrPSctJzsKICAgICAgICBpID0gLWk7CiAgICB9IGVsc2UgewogICAgICAgICpidWYrKz0nKyc7CiAgICB9CiAgICAvLyAqYWx3YXlzKiB3cml0ZSBkb3duIHRoZSBsYXN0IDQgZGlnaXRzLCBldmVuIGlmIHRoZXkgYXJlIHplcm9lcwogICAgLy8gKHRoZXknbGwgYmVjb21lIHRoZSA0IGRpZ2l0cyBhZnRlciB0aGUgZGVjaW1hbCBkb3QpCiAgICBmb3IoOyBicCE9Yis0OyApIHsKICAgICAgICAqYnArKyA9ICcwJyArIGklMTA7CiAgICAgICAgaS89MTA7CiAgICB9CiAgICAqYnArKz0nLic7CiAgICAvLyB3cml0ZSBkb3duIHRoZSByZW1haW5pbmcgZGlnaXRzLCB3cml0aW5nIGF0IGxlYXN0IG9uZQogICAgZG8gewogICAgICAgICpicCsrID0gJzAnICsgaSUxMDsKICAgICAgICBpLz0xMDsKICAgIH0gd2hpbGUoaSAhPSAwKTsKICAgIC8vIGJwIGlzIGF0IHRoZSBjaGFyYWN0ZXIgYWZ0ZXIgdGhlIGxhc3QsIHN0ZXAgYmFjawogICAgLS1icDsKICAgIC8vIGRhdGEgaXMgbm93IGludG8gYiAqaW4gcmV2ZXJzZWQgb3JkZXIqOwogICAgLy8gcmV2ZXJzZS1jb3B5IGl0IGludG8gdGhlIHVzZXItcHJvdmlkZWQgYnVmZmVyCiAgICB3aGlsZShidWYhPWxpbSkgewogICAgICAgICpidWYrKyA9ICpicDsKICAgICAgICAvLyBjaGVjayBiZWZvcmUgZGVjcmVtZW50aW5nLCBhcyBhIHBvaW50ZXIgdG8gb25lLWJlZm9yZS1maXJzdAogICAgICAgIC8vIGlzIG5vdCBhbGxvd2VkIGluIEMKICAgICAgICBpZihicCA9PSBiKSBicmVhazsKICAgICAgICAtLWJwOwogICAgfQogICAgaWYoYnVmIT1saW0pICpidWY9MDsgICAgLy8gInJlZ3VsYXIiIGNhc2U6IHRlcm1pbmF0ZSAqYWZ0ZXIqCiAgICBlbHNlICAgICAgICAgbGltWy0xXT0wOyAvLyBiYWQgY2FzZTogdHJ1bmNhdGUKICAgIHJldHVybiBidWY7Cn0KCnZvaWQgZG9mb3JtYXQoY2hhciAqYnVmLCBjaGFyICpsaW0sIGRvdWJsZSBhLCBkb3VibGUgYikgewogICAgaWYoYnVmPT1saW0pIHJldHVybjsgLy8gY2Fubm90IGRvIGFueXRoaW5nCiAgICAqYnVmKys9J3snOwogICAgaWYoYnVmPT1saW0pIGdvdG8gZW5kOwogICAgYnVmID0gZm10cDA0ZihidWYsIGxpbSwgYSk7CiAgICBpZihidWY9PWxpbSkgcmV0dXJuOyAvLyBhbHJlYWR5IHRlcm1pbmF0ZWQgYnkgZm10cDA0ZgogICAgKmJ1ZisrPScsJzsKICAgIGlmKGJ1Zj09bGltKSBnb3RvIGVuZDsKICAgIGJ1ZiA9IGZtdHAwNGYoYnVmLCBsaW0sIGIpOwogICAgaWYoYnVmPT1saW0pIHJldHVybjsgLy8gaWRlbQogICAgKmJ1ZisrPSd9JzsKICAgIGlmKGJ1Zj09bGltKSBnb3RvIGVuZDsKICAgICpidWYrKz0wOwplbmQ6CiAgICBsaW1bLTFdPTA7ICAgLy8gYWx3YXlzIHRlcm1pbmF0ZQp9CgppbnQgbWFpbigpIHsKICAgIGRvdWJsZSB0ZXN0X2Nhc2VzW10gPSB7MC4sIDEuLCAxMDAuLCAxLjIzNDU2NzgsIDEyMzQ1LjY3OCwgMy4xNDE1LCA5LjExNTI1MSwgOTk5OTkuMTIzNCwgMC59OwogICAgY2hhciBidWYxWzIyXTsKICAgIGNoYXIgYnVmMlsyNTZdOwogICAgY2hhciAqYnVmMnIgPSBidWYyKzEyODsKICAgIGZvcihpbnQgaT0wLCBuPShzaXplb2YodGVzdF9jYXNlcykvc2l6ZW9mKCp0ZXN0X2Nhc2VzKSktMTsgaTxuOyArK2kpIHsKICAgICAgICBmb3IoaW50IHNnbiA9IDA7IHNnbjw0OyArK3NnbikgewogICAgICAgICAgICBtZW1zZXQoYnVmMiwgMjU1LCBzaXplb2YoYnVmMikpOwogICAgICAgICAgICBkb3VibGUgYSA9IHRlc3RfY2FzZXNbaV07CiAgICAgICAgICAgIGlmKHNnbiYxKSBhID0gLWE7CiAgICAgICAgICAgIGRvdWJsZSBiID0gdGVzdF9jYXNlc1tpKzFdOwogICAgICAgICAgICBpZihzZ24mMikgYiA9IC1iOwogICAgICAgICAgICBzbnByaW50ZihidWYxLCBzaXplb2YoYnVmMSksICJ7JSswLjRmLCUrMC40Zn0iLCBhLCBiKTsKICAgICAgICAgICAgcHV0cyhidWYxKTsKICAgICAgICAgICAgZG9mb3JtYXQoYnVmMnIsIGJ1ZjJyKzIyLCBhLCBiKTsKICAgICAgICAgICAgcHV0cyhidWYycik7CiAgICAgICAgICAgIGlmKHN0cmNtcChidWYyciwgYnVmMSkpIHsKICAgICAgICAgICAgICAgIHByaW50ZigiYnVmMSBbJXNdICE9IGJ1ZjJyIFslc11cbiIsIGJ1ZjEsIGJ1ZjJyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IoY29uc3QgY2hhciAqcD1idWYyOyBwPGJ1ZjJyOyArK3ApIHsKICAgICAgICAgICAgICAgIGlmKCh1bnNpZ25lZCBjaGFyKSgqcCkhPTI1NSkgewogICAgICAgICAgICAgICAgICAgIHByaW50ZigidW5leHBlY3RlZCAlZCBhdCAlZFxuIiwgKnAsIChpbnQpKHAtYnVmMikpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvcihjb25zdCBjaGFyICpwPWJ1ZjJyKzIyOyBwPGJ1ZjIgKyBzaXplb2YoYnVmMik7ICsrcCkgewogICAgICAgICAgICAgICAgaWYoKHVuc2lnbmVkIGNoYXIpKCpwKSE9MjU1KSB7CiAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCJ1bmV4cGVjdGVkICVkIGF0ICVkXG4iLCAqcCwgKGludCkocC1idWYyKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gMDsKCn0K
{+0.0000,+1.0000}
{+0.0000,+1.0000}
{-0.0000,+1.0000}
{-0.0000,+1.0000}
{+0.0000,-1.0000}
{+0.0000,-1.0000}
{-0.0000,-1.0000}
{-0.0000,-1.0000}
{+1.0000,+100.0000}
{+1.0000,+100.0000}
{-1.0000,+100.0000}
{-1.0000,+100.0000}
{+1.0000,-100.0000}
{+1.0000,-100.0000}
{-1.0000,-100.0000}
{-1.0000,-100.0000}
{+100.0000,+1.2346}
{+100.0000,+1.2346}
{-100.0000,+1.2346}
{-100.0000,+1.2346}
{+100.0000,-1.2346}
{+100.0000,-1.2346}
{-100.0000,-1.2346}
{-100.0000,-1.2346}
{+1.2346,+12345.6780}
{+1.2346,+12345.6780}
{-1.2346,+12345.6780}
{-1.2346,+12345.6780}
{+1.2346,-12345.6780}
{+1.2346,-12345.6780}
{-1.2346,-12345.6780}
{-1.2346,-12345.6780}
{+12345.6780,+3.1415}
{+12345.6780,+3.1415}
{-12345.6780,+3.1415}
{-12345.6780,+3.1415}
{+12345.6780,-3.1415}
{+12345.6780,-3.1415}
{-12345.6780,-3.1415}
{-12345.6780,-3.1415}
{+3.1415,+9.1153}
{+3.1415,+9.1153}
{-3.1415,+9.1153}
{-3.1415,+9.1153}
{+3.1415,-9.1153}
{+3.1415,-9.1153}
{-3.1415,-9.1153}
{-3.1415,-9.1153}
{+9.1153,+99999.1234}
{+9.1153,+99999.1234}
{-9.1153,+99999.1234}
{-9.1153,+99999.1234}
{+9.1153,-99999.1234}
{+9.1153,-99999.1234}
{-9.1153,-99999.1234}
{-9.1153,-99999.1234}
{+99999.1234,+0.0000}
{+99999.1234,+0.0000}
{-99999.1234,+0.0000}
{-99999.1234,+0.0000}
{+99999.1234,-0.0000}
{+99999.1234,-0.0000}
{-99999.1234,-0.0000}
{-99999.1234,-0.0000}