-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathfloat_.d
More file actions
77 lines (77 loc) · 2.71 KB
/
float_.d
File metadata and controls
77 lines (77 loc) · 2.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
module util.float_;
// hacky float formatter (TODO: replace with dedicated algorithm)
import core.stdc.stdio,core.stdc.float_,std.conv,std.math,std.complex,std.traits;
enum int maxDigits10(T)=cast(int)ceil(T.mant_dig*log10(double(FLT_RADIX)))+5;
bool containsDotOrExp(scope const string s){
foreach(ch; s)
if(ch=='.'||ch=='e'||ch=='E')
return true;
return false;
}
bool roundTrips(T)(scope const string s,T x)if(isFloatingPoint!T){
try{
auto t=cast()s;
return parse!T(t)==x;
}catch (ConvException){
return false;
}
}
string normalizeExponent(T)(string s, T x)if(isFloatingPoint!T){
size_t epos=size_t.max;
foreach(i,ch;s) if(ch=='e'||ch=='E'){epos=i;break;}
if(epos==size_t.max) return s;
auto mant=s[0..epos],exp=s[epos+1..$],esign='+';
size_t j=0;
if(exp.length&&(exp[0]=='+'||exp[0]=='-')) esign=exp[0],j=1;
for(;j<exp.length&&exp[j]=='0';++j){}
auto digits=j<exp.length?exp[j..$]:"0";
auto candidate=mant~(esign=='-'?"e-":"e")~digits;
return roundTrips!T(candidate,x)?candidate:s;
}
string snprintfG(T)(T x,int prec)if(isFloatingPoint!T){
char[64] sbuf;
for(size_t cap=64;;cap*=2){
auto buf=cap==64?sbuf[]:new char[](cap);
static if(is(T==real)){
static assert(T.sizeof==16);
auto n=snprintf(buf.ptr,buf.length,"%.*Lg",prec,x);
}else auto n=snprintf(buf.ptr,buf.length,"%.*g",prec,cast(double)x);
if(n>=0&&cast(size_t)n<buf.length)
return buf[0..cast(size_t)n].idup;
}
}
string snprintfHex(T)(T x)if(isFloatingPoint!T){
char[64] sbuf;
for(size_t cap=64;;cap*=2){
auto buf=cap==64?sbuf[]:new char[](cap);
static if(is(T==real)) auto n=snprintf(buf.ptr,buf.length,"%La",x);
else auto n=snprintf(buf.ptr,buf.length,"%a",cast(double)x);
if(n>=0&&cast(size_t)n<buf.length)
return buf[0..cast(size_t)n].idup;
}
}
string toStringRT(T)(T x,bool pythonStyle=true)if(isFloatingPoint!T){
if(isNaN(x)) return "nan";
if(isInfinity(x)) return signbit(x)?"-inf":"inf";
if(x==0){
if(signbit(x)) return pythonStyle?"-0.0":"-0";
return pythonStyle?"0.0" :"0";
}
enum int maxP=maxDigits10!T;
foreach(p;1..maxP+1){
auto s=snprintfG!T(x,p);
s=normalizeExponent!T(s,x);
if(pythonStyle&&!containsDotOrExp(s)){
auto withDot=s~".0";
if(roundTrips!T(withDot,x))
s=withDot;
}
if(roundTrips!T(s,x))
return s;
}
return snprintfHex!T(x);
}
string toStringRT(T)(Complex!T x,bool pythonStyle=false)if(isFloatingPoint!T){
if(x.re!=0) return toStringRT(x.re,pythonStyle)~(x.im<0?"":"+")~toStringRT(x.im,pythonStyle)~"i";
return toStringRT(x.im,pythonStyle)~"i";
}