Mercurial > projects > decimal
comparison src/decimal/context.d @ 0:42cf4db6be32
Creation
author | Paul (paul.d.anderson@comcast.net) |
---|---|
date | Sat, 13 Mar 2010 13:22:25 -0800 |
parents | |
children | abf9d7974708 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:42cf4db6be32 |
---|---|
1 module decimal.context; | |
2 | |
3 import decimal.decimal; | |
4 import std.string; | |
5 | |
6 //-------------------------- | |
7 // | |
8 // DecimalContext struct | |
9 // | |
10 //-------------------------- | |
11 | |
12 /** | |
13 * Enumeration of available rounding modes. | |
14 */ | |
15 public enum Rounding { | |
16 HALF_EVEN, | |
17 HALF_DOWN, | |
18 HALF_UP, | |
19 DOWN, | |
20 UP, | |
21 FLOOR, | |
22 CEILING, | |
23 } | |
24 | |
25 | |
26 // context flags | |
27 public enum : ubyte { | |
28 CLAMPED = 0x01, | |
29 DIVISION_BY_ZERO = 0x02, | |
30 INEXACT = 0x04, | |
31 INVALID_OPERATION = 0x08, | |
32 OVERFLOW = 0x10, | |
33 ROUNDED = 0x20, | |
34 SUBNORMAL = 0x40, | |
35 UNDERFLOW = 0x80 | |
36 } | |
37 | |
38 /+public: | |
39 static immutable ubyte CLAMPED = 0x01; | |
40 static immutable ubyte DIVISION_BY_ZERO = 0x02; | |
41 static immutable ubyte INEXACT = 0x04; | |
42 static immutable ubyte INVALID_OPERATION = 0x08; | |
43 static immutable ubyte OVERFLOW = 0x10; | |
44 static immutable ubyte ROUNDED = 0x20; | |
45 static immutable ubyte SUBNORMAL = 0x40; | |
46 static immutable ubyte UNDERFLOW = 0x80;+/ | |
47 | |
48 /** | |
49 * Context for Decimal mathematic operations | |
50 */ | |
51 public struct DecimalContext { | |
52 public: | |
53 Rounding mode = Rounding.HALF_EVEN; | |
54 uint precision = 9; | |
55 ubyte traps; | |
56 ubyte flags; | |
57 int eMin = -98; | |
58 int eMax = 99; | |
59 | |
60 const int eTiny() { | |
61 return eMin - (precision - 1); | |
62 } | |
63 | |
64 /// Returns the number of decimal digits in this context. | |
65 const uint dig() { | |
66 return precision; | |
67 } | |
68 | |
69 /// returns the smallest available increment to one in this context | |
70 const Decimal epsilon() { | |
71 return Decimal(1,-precision); | |
72 } | |
73 | |
74 /// Returns the number of binary digits in this context. | |
75 const int mant_dig() { | |
76 return cast(int)(precision/LOG2); | |
77 } | |
78 | |
79 const int min_exp() { | |
80 return cast(int)(eMin/LOG2); | |
81 } | |
82 | |
83 const int max_exp() { | |
84 return cast(int)(eMax/LOG2); | |
85 } | |
86 | |
87 const int min_10_exp() { | |
88 return eMin; | |
89 } | |
90 | |
91 const int max_10_exp() { | |
92 return eMax; | |
93 } | |
94 | |
95 /// Returns the maximum representable normal value in the current context. | |
96 // TODO: Replace this formula with a single execution when precision or eMax is changed. | |
97 const Decimal max() { | |
98 string cstr = "9." ~ repeat("9", precision-1) ~ "E" ~ format("%d", eMax); | |
99 return Decimal(cstr); | |
100 } | |
101 | |
102 // Returns the minimum representable normal value in the current context. | |
103 const Decimal min_normal() { | |
104 return Decimal(1, eMin); | |
105 } | |
106 | |
107 // Returns the minimum representable subnormal value in the current context. | |
108 const Decimal min() { | |
109 return Decimal(1, eTiny); | |
110 } | |
111 | |
112 /+ public const int getPrecision() { | |
113 return precision; | |
114 } | |
115 | |
116 public void setPrecision(int precision) { | |
117 this.precision = precision; | |
118 }+/ | |
119 | |
120 const void setFlag(const ubyte flag, const bool value = true) { | |
121 if (value) { | |
122 context.flags |= flag; | |
123 } | |
124 else { | |
125 context.flags &= !flag; | |
126 } | |
127 } | |
128 | |
129 public bool getFlag(const ubyte flag) { | |
130 return (context.flags & flag) == flag; | |
131 } | |
132 | |
133 public void clearFlags() { | |
134 context.flags = 0; | |
135 } | |
136 | |
137 | |
138 }; // end struct DecimalContext | |
139 | |
140 public: | |
141 // default context | |
142 immutable DecimalContext DEFAULT_CONTEXT = DecimalContext(); | |
143 | |
144 private: | |
145 // context stack | |
146 struct ContextStack { | |
147 private: | |
148 DecimalContext[] stack = [ DEFAULT_CONTEXT ]; | |
149 uint capacity = 1; | |
150 uint count = 1; | |
151 | |
152 public void push() { | |
153 if (count >= capacity) { | |
154 capacity *= 2; | |
155 stack.length = capacity; | |
156 } | |
157 count++; | |
158 stack[count-1] = context; | |
159 } | |
160 | |
161 public void pop() { | |
162 if (count == 0) { | |
163 push(); | |
164 } | |
165 if (count == 1) { | |
166 context = stack[0]; | |
167 } | |
168 else { | |
169 count--; | |
170 context = stack[count-1]; | |
171 } | |
172 } | |
173 | |
174 } // end struct ContextStack | |
175 | |
176 //-------------------------- | |
177 // | |
178 // Emd of DecimalContext struct | |
179 // | |
180 //-------------------------- | |
181 | |
182 |