30 {
31 fesetround(FE_TONEAREST);
32
33 const wchar_t* subprefixes = SUBPREFIXES;
34 const wchar_t prefixes[] = L"KMGTPEZY";
35 if(decimal == 0 || mult == 0){
37 }
38 if(decimal > UINTMAX_MAX / 10){
40 }
41 unsigned consumed = 0;
42 uintmax_t dv = mult;
43 if(decimal <= val || val == 0){
44
45 while((val / decimal) >= dv && consumed < sizeof(prefixes) / sizeof(*prefixes)){
46 dv *= mult;
47 ++consumed;
48 if(UINTMAX_MAX / dv < mult){
49 break;
50 }
51 }
52 }else{
53 while(val < decimal && consumed < sizeof(prefixes) / sizeof(*prefixes)){
54 val *= mult;
55 ++consumed;
56 if(UINTMAX_MAX / dv < mult){
57 break;
58 }
59 }
60 }
61 int sprintfed;
62 if(dv != mult){
63 if((val / decimal) / dv > 0){
64 ++consumed;
65 }else{
66 dv /= mult;
67 }
68 val /= decimal;
69
70
71
72
73
74 if(omitdec && (val % dv) == 0){
75 sprintfed = snprintf(buf, s, "%" PRIu64 "%lc", (uint64_t)(val / dv),
76 (wint_t)prefixes[consumed - 1]);
77 }else{
78 sprintfed = snprintf(buf, s, "%.2f%lc", (double)val / dv,
79 (wint_t)prefixes[consumed - 1]);
80 }
81 if(sprintfed < 0){
83 }
84 if(uprefix){
85 if((size_t)sprintfed < s){
86 buf[sprintfed] = uprefix;
87 buf[++sprintfed] = '\0';
88 }
89 }
90 return buf;
91 }
92
93
94 if(omitdec && val % decimal == 0){
95 if(consumed){
96 sprintfed = snprintf(buf, s, "%" PRIu64 "%lc", (uint64_t)(val / decimal),
97 (wint_t)subprefixes[consumed - 1]);
98 }else{
99 sprintfed = snprintf(buf, s, "%" PRIu64, (uint64_t)(val / decimal));
100 }
101 }else{
102 if(consumed){
103 sprintfed = snprintf(buf, s, "%.2f%lc", (double)val / decimal,
104 (wint_t)subprefixes[consumed - 1]);
105 }else{
106 sprintfed = snprintf(buf, s, "%.2f", (double)val / decimal);
107 }
108 }
109 if(sprintfed < 0){
111 }
112 if(consumed && uprefix){
113 if((size_t)sprintfed < s){
114 buf[sprintfed] = uprefix;
115 buf[++sprintfed] = '\0';
116 }
117 }
118 return buf;
119}