Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cstdlib>
- // #include <sstream>
- #include <string>
- // #include <string.h>
- #include <iostream>
- #include <functional>
- #include <iomanip>
- #include <algorithm>
- #include <cmath>
- #undef _CRT_DEPRECATE_TEXT
- #undef _CRT_NONSTDC_DEPRECATE
- #undef _CRT_INSECURE_DEPRECATE
- using uint32_t = unsigned int;
- using u32 = uint32_t;
- char *ecvt(double x, int n, int *dp, int *sign)
- {
- static char buf[16];
- char tmp[32];
- int i, j;
- if (n - 1U > 15)
- n = 15;
- sprintf(tmp, "%.*e", n - 1, x);
- i = *sign = (tmp[0] == '-');
- for (j = 0; tmp[i] != 'e'; j += (tmp[i++] != '.'))
- buf[j] = tmp[i];
- buf[j] = 0;
- *dp = atoi(tmp + i + 1) + 1;
- return buf;
- }
- // char *ecvt2(double x, int n, int *dp, int *sign)
- // {
- // char tmp[32];
- // n = std::min(n, 15);
- // std::sprintf(tmp, "%.*e", n - 1, x);
- // std::string doubleString = std::string(tmp);
- // *sign = doubleString[0] == '-';
- // doubleString.erase(std::remove(doubleString.begin(), doubleString.end(), 'e'), doubleString.end());
- // doubleString.erase(std::remove(doubleString.begin(), doubleString.end(), '-'), doubleString.end());
- // doubleString.erase(std::remove(doubleString.begin(), doubleString.end(), '.'), doubleString.end());
- // *dp =doubleString.length();
- // return &doubleString[0];
- // }
- char* ecvt3(double x, int n, int *dp, int *sign)
- {
- char tmp[32];
- n = std::min(n, 15);
- std::sprintf(tmp, "%.*e", n - 1, x);
- std::string str(tmp);
- *sign = str[0] == '-';
- if (str == "inf" || str == "-inf")
- {
- *dp = 1;
- return "1#INF";
- }
- else if ((str == "nan" || str == "-nan"))
- {
- *dp = 1;
- return "1#QNAN";
- }
- else if ((str == "-nan(ind)" || str == "-nan(ind)"))
- {
- *dp = 1;
- return "1#IND";
- }
- else
- {
- *dp = std::atoi(tmp + str.find('e') + 1) + 1;
- }
- int index = 0;
- str.erase(
- std::remove_if(
- str.begin(),
- str.end(),
- [&index, n](unsigned char x){
- bool ShouldRemove = index > n || x == '+' || x == 'e' || x == '-' || x == '.';
- if(!ShouldRemove)
- ++index;
- return ShouldRemove;
- }
- ));
- char *cstr = new char[str.length() + 1];
- strcpy(cstr, str.c_str());
- return cstr;
- }
- namespace std
- {
- inline double round(double v, int p)
- {
- return std::round(v * std::pow(10, p)) / std::pow(10, p);
- }
- } // namespace std
- void FloatToString3(double f, char* sz)
- {
- std::string str = std::to_string(3.1415926);
- char *cstr = new char[str.length() + 1];
- strcpy(cstr, str.c_str());
- sz = cstr;
- }
- void FloatToString2(double f, char* sz)
- {
- static const int digitCount = 6;
- bool isNegative = f < 0.0f;
- f = std::round(f, digitCount);
- std::snprintf(sz, 128, "%c%lf", isNegative ? '-' : 0, f);
- }
- void FloatToString(float f, char* sz, std::function<char*(double, int, int*, int*)> function)
- {
- char* buffer = sz + 1;
- static const int digitCount = 6;
- int decimal, sign;
- // ecvt rounds the string for us: http://www.datafocus.com/docs/man3/ecvt.3.asp
- char* end = function(f, digitCount, &decimal, &sign);
- if (sign != 0) (*buffer++) = '-';
- int count = digitCount;
- if (decimal > digitCount)
- {
- // We use the scientific notation: P.MeX
- (*buffer++) = (*end++); // P is one character.
- (*buffer++) = '.';
- // Mantissa (cleaned for zeroes)
- for (--count; count > 0; --count) if (end[count - 1] != '0') break;
- for (int i = 0; i < count; ++i) (*buffer++) = (*end++);
- if (buffer[-1] == '.') --buffer;
- // Exponent
- (*buffer++) = 'e';
- u32 exponent = decimal - 1; // X
- if (exponent >= 10) (*buffer++) = (char) ('0' + (exponent / 10));
- (*buffer++) = (char) ('0' + (exponent % 10));
- (*buffer) = 0;
- return;
- }
- else if (decimal > 0)
- {
- // Simple number: A.B
- for (int i = 0; i < decimal; ++i) (*buffer++) = (*end++);
- if (decimal < digitCount) (*buffer++) = '.';
- count = digitCount - decimal;
- }
- else if (decimal < -digitCount)
- {
- // What case is this?
- decimal = count = 0;
- }
- else if (decimal < 0 || (decimal == 0 && *end != '0'))
- {
- // Tiny number: 0.Me-X
- (*buffer++) = '0'; (*buffer++) = '.';
- for (int i = 0; i < -decimal; ++i) (*buffer++) = '0';
- count = digitCount + decimal;
- }
- for (; count > 0; --count) if (end[count - 1] != '0') break;
- for (int i = 0; i < count; ++i) (*buffer++) = (*end++);
- if (decimal == 0 && count == 0) (*buffer++) = '0';
- if (buffer[-1] == '.') --buffer;
- (*buffer) = 0;
- }
- void ecvt_wrapper(float source)
- {
- // std::cout << "------------------"<< source << "------------------------------" << std::endl;
- // int decimal, sign;
- // char *buffer;
- // int precision = 10;
- // buffer = ecvt(source, precision, &decimal, &sign);
- // std::cout << "Musl implem: " << buffer << " sign: " << sign << " decimal: " << decimal << std::endl;
- // buffer = ecvt2(source, precision, &decimal, &sign);
- // std::cout << "New implem: " << buffer << " sign: " << sign << " decimal: " << decimal << std::endl;
- // buffer = _ecvt(source, precision, &decimal, &sign);
- // std::cout << "Native implem: " << buffer << " sign: " << sign << " decimal: " << decimal << std::endl;
- std::cout << "----------------------"<<source<<"--------------------------" << std::endl;
- char sz[128];
- float so = static_cast<float>(source);
- // FloatToString(so, sz,ecvt2);
- // std::cout << "New implem: " << sz + 1 << std::endl;
- FloatToString(so, sz,ecvt3);
- std::cout << "New implem++: " << sz + 1 << std::endl;
- FloatToString(so, sz,_ecvt);
- std::cout << "Native implem: " << sz + 1 << std::endl;
- // FloatToString(so, sz,ecvt);
- // std::cout << "MUSL implem: " << sz + 1 << std::endl;
- FloatToString2(so, sz);
- std::cout << "SNPRINTF implem: " << sz + 1 << std::endl;
- FloatToString3(so, sz);
- std::cout << "to_string: " << sz + 1 << std::endl;
- }
- int main()
- {
- ecvt_wrapper(-3.1415926535);
- ecvt_wrapper(-3.1415926535);
- ecvt_wrapper(-12415.1415926535);
- ecvt_wrapper(+12415.1415926535);
- ecvt_wrapper(+12415.12034578);
- ecvt_wrapper(+12415.120341111118);
- ecvt_wrapper(+0.120341111118);
- ecvt_wrapper(-0.120341111118);
- ecvt_wrapper(0.5);
- ecvt_wrapper(0.0);
- ecvt_wrapper(4e5);
- ecvt_wrapper(4e-5);
- ecvt_wrapper(-4e-5);
- ecvt_wrapper(4e5);
- ecvt_wrapper(4e25);
- ecvt_wrapper(-4e25);
- ecvt_wrapper(4e-25);
- ecvt_wrapper(-4e-25);
- ecvt_wrapper(std::numeric_limits<float>::max());
- ecvt_wrapper(std::numeric_limits<float>::min());
- ecvt_wrapper(std::numeric_limits<double>::max());
- ecvt_wrapper(std::numeric_limits<double>::min());
- ecvt_wrapper(-std::numeric_limits<float>::max());
- ecvt_wrapper(-std::numeric_limits<float>::min());
- ecvt_wrapper(-std::numeric_limits<double>::max());
- ecvt_wrapper(-std::numeric_limits<double>::min());
- ecvt_wrapper(std::numeric_limits<float>::quiet_NaN());
- ecvt_wrapper(-std::numeric_limits<float>::quiet_NaN());
- ecvt_wrapper(std::numeric_limits<float>::signaling_NaN());
- ecvt_wrapper(-std::numeric_limits<float>::signaling_NaN());
- ecvt_wrapper(std::numeric_limits<double>::quiet_NaN());
- ecvt_wrapper(-std::numeric_limits<double>::quiet_NaN());
- ecvt_wrapper(std::numeric_limits<double>::signaling_NaN());
- ecvt_wrapper(-std::numeric_limits<double>::signaling_NaN());
- ecvt_wrapper(1);
- ecvt_wrapper(std::numeric_limits<float>::infinity());
- ecvt_wrapper(std::numeric_limits<double>::infinity());
- ecvt_wrapper(-std::numeric_limits<float>::infinity());
- ecvt_wrapper(-std::numeric_limits<double>::infinity());
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement