1use std::fmt;
17use std::marker::PhantomData;
18use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
19
20use libc::c_uint;
21
22#[derive(Clone)]
41pub struct Context<D> {
42 pub(crate) inner: decnumber_sys::decContext,
43 pub(crate) _phantom: PhantomData<D>,
44}
45
46impl<D> fmt::Debug for Context<D> {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 f.debug_struct("Context")
49 .field("clamp", &self.inner.clamp)
50 .field("digits", &self.inner.digits)
51 .field("emax", &self.inner.emax)
52 .field("emin", &self.inner.emin)
53 .field("rounding", &self.rounding())
54 .field("traps", &self.inner.traps)
55 .finish()
56 }
57}
58
59impl<D> Context<D> {
60 pub fn rounding(&self) -> Rounding {
62 Rounding::from_c(self.inner.round)
63 }
64
65 pub fn set_rounding(&mut self, rounding: Rounding) {
67 self.inner.round = rounding.to_c();
68 }
69
70 pub fn status(&self) -> Status {
72 Status {
73 inner: self.inner.status,
74 }
75 }
76
77 pub fn set_status(&mut self, status: Status) {
79 self.inner.status = status.inner;
80 }
81
82 pub fn clear_status(&mut self) {
84 self.inner.status = 0;
85 }
86}
87
88#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
95pub enum Rounding {
96 Ceiling,
98 Down,
100 Floor,
102 HalfDown,
104 HalfEven,
106 HalfUp,
108 Up,
110 ZeroFiveUp,
115}
116
117impl Default for Rounding {
118 fn default() -> Rounding {
119 Rounding::HalfEven
120 }
121}
122
123impl Rounding {
124 fn from_c(c: c_uint) -> Rounding {
125 match c {
126 decnumber_sys::DEC_ROUND_CEILING => Rounding::Ceiling,
127 decnumber_sys::DEC_ROUND_DOWN => Rounding::Down,
128 decnumber_sys::DEC_ROUND_FLOOR => Rounding::Floor,
129 decnumber_sys::DEC_ROUND_HALF_DOWN => Rounding::HalfDown,
130 decnumber_sys::DEC_ROUND_HALF_EVEN => Rounding::HalfEven,
131 decnumber_sys::DEC_ROUND_HALF_UP => Rounding::HalfUp,
132 decnumber_sys::DEC_ROUND_UP => Rounding::Up,
133 decnumber_sys::DEC_ROUND_05UP => Rounding::ZeroFiveUp,
134 _ => unreachable!("invalid C rounding value"),
135 }
136 }
137
138 fn to_c(&self) -> c_uint {
139 match self {
140 Rounding::Ceiling => decnumber_sys::DEC_ROUND_CEILING,
141 Rounding::Down => decnumber_sys::DEC_ROUND_DOWN,
142 Rounding::Floor => decnumber_sys::DEC_ROUND_FLOOR,
143 Rounding::HalfDown => decnumber_sys::DEC_ROUND_HALF_DOWN,
144 Rounding::HalfEven => decnumber_sys::DEC_ROUND_HALF_EVEN,
145 Rounding::HalfUp => decnumber_sys::DEC_ROUND_HALF_UP,
146 Rounding::Up => decnumber_sys::DEC_ROUND_UP,
147 Rounding::ZeroFiveUp => decnumber_sys::DEC_ROUND_05UP,
148 }
149 }
150}
151
152#[derive(Clone, Copy, Eq, PartialEq, Hash)]
161pub struct Status {
162 inner: u32,
163}
164
165impl fmt::Debug for Status {
166 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167 f.debug_struct("Status")
168 .field("conversion_syntax", &self.conversion_syntax())
169 .field("division_by_zero", &self.division_by_zero())
170 .field("division_impossible", &self.division_impossible())
171 .field("division_undefined", &self.division_undefined())
172 .field("insufficient_storage", &self.insufficient_storage())
173 .field("inexact", &self.inexact())
174 .field("invalid_context", &self.invalid_context())
175 .field("invalid_operation", &self.invalid_operation())
176 .field("overflow", &self.overflow())
177 .field("clamped", &self.clamped())
178 .field("rounded", &self.rounded())
179 .field("subnormal", &self.subnormal())
180 .field("underflow", &self.underflow())
181 .field("raw", &self.inner)
182 .finish()
183 }
184}
185
186impl Status {
187 pub fn any(&self) -> bool {
189 self.inner != 0
190 }
191
192 pub fn conversion_syntax(&self) -> bool {
197 self.inner & decnumber_sys::DEC_Conversion_syntax != 0
198 }
199
200 pub fn set_conversion_syntax(&mut self) {
202 self.inner |= decnumber_sys::DEC_Conversion_syntax;
203 }
204
205 pub fn division_by_zero(&self) -> bool {
209 self.inner & decnumber_sys::DEC_Division_by_zero != 0
210 }
211
212 pub fn set_division_by_zero(&mut self) {
214 self.inner |= decnumber_sys::DEC_Division_by_zero;
215 }
216
217 pub fn division_impossible(&self) -> bool {
222 self.inner & decnumber_sys::DEC_Division_impossible != 0
223 }
224
225 pub fn set_division_impossible(&mut self) {
227 self.inner |= decnumber_sys::DEC_Division_impossible;
228 }
229
230 pub fn division_undefined(&self) -> bool {
234 self.inner & decnumber_sys::DEC_Division_undefined != 0
235 }
236
237 pub fn set_division_undefined(&mut self) {
239 self.inner |= decnumber_sys::DEC_Division_undefined;
240 }
241
242 pub fn insufficient_storage(&self) -> bool {
246 self.inner & decnumber_sys::DEC_Insufficient_storage != 0
247 }
248
249 pub fn set_insufficient_storage(&mut self) {
251 self.inner |= decnumber_sys::DEC_Insufficient_storage;
252 }
253
254 pub fn inexact(&self) -> bool {
259 self.inner & decnumber_sys::DEC_Inexact != 0
260 }
261
262 pub fn set_inexact(&mut self) {
264 self.inner |= decnumber_sys::DEC_Inexact;
265 }
266
267 pub fn invalid_context(&self) -> bool {
275 self.inner & decnumber_sys::DEC_Invalid_context != 0
276 }
277
278 pub fn set_invalid_context(&mut self) {
280 self.inner |= decnumber_sys::DEC_Invalid_context;
281 }
282
283 pub fn invalid_operation(&self) -> bool {
287 self.inner & decnumber_sys::DEC_Invalid_operation != 0
288 }
289
290 pub fn set_invalid_operation(&mut self) {
292 self.inner |= decnumber_sys::DEC_Invalid_operation;
293 }
294
295 pub fn overflow(&self) -> bool {
300 self.inner & decnumber_sys::DEC_Overflow != 0
301 }
302
303 pub fn set_overflow(&mut self) {
305 self.inner |= decnumber_sys::DEC_Overflow;
306 }
307
308 pub fn clamped(&self) -> bool {
314 self.inner & decnumber_sys::DEC_Clamped != 0
315 }
316
317 pub fn set_clamped(&mut self) {
319 self.inner |= decnumber_sys::DEC_Clamped;
320 }
321
322 pub fn rounded(&self) -> bool {
327 self.inner & decnumber_sys::DEC_Rounded != 0
328 }
329
330 pub fn set_rounded(&mut self) {
332 self.inner |= decnumber_sys::DEC_Rounded;
333 }
334
335 pub fn subnormal(&self) -> bool {
340 self.inner & decnumber_sys::DEC_Subnormal != 0
341 }
342
343 pub fn set_subnormal(&mut self) {
345 self.inner |= decnumber_sys::DEC_Subnormal;
346 }
347
348 pub fn underflow(&self) -> bool {
352 self.inner & decnumber_sys::DEC_Underflow != 0
353 }
354
355 pub fn set_underflow(&mut self) {
357 self.inner |= decnumber_sys::DEC_Underflow;
358 }
359}
360
361impl Default for Status {
362 fn default() -> Self {
363 Status { inner: 0 }
364 }
365}
366
367impl BitAnd for Status {
368 type Output = Status;
369
370 fn bitand(self, rhs: Status) -> Status {
371 Status {
372 inner: self.inner & rhs.inner,
373 }
374 }
375}
376
377impl BitAndAssign for Status {
378 fn bitand_assign(&mut self, rhs: Status) {
379 self.inner &= rhs.inner;
380 }
381}
382
383impl BitOr for Status {
384 type Output = Status;
385
386 fn bitor(self, rhs: Status) -> Status {
387 Status {
388 inner: self.inner | rhs.inner,
389 }
390 }
391}
392
393impl BitOrAssign for Status {
394 fn bitor_assign(&mut self, rhs: Status) {
395 self.inner |= rhs.inner;
396 }
397}
398
399#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
406pub enum Class {
407 SignalingNan,
409 QuietNan,
411 NegInfinity,
413 NegNormal,
415 NegSubnormal,
417 NegZero,
419 PosZero,
421 PosSubnormal,
423 PosNormal,
425 PosInfinity,
427}
428
429impl Class {
430 pub(crate) fn from_c(c: c_uint) -> Class {
431 match c {
432 decnumber_sys::DEC_CLASS_SNAN => Class::SignalingNan,
433 decnumber_sys::DEC_CLASS_QNAN => Class::QuietNan,
434 decnumber_sys::DEC_CLASS_NEG_INF => Class::NegInfinity,
435 decnumber_sys::DEC_CLASS_NEG_NORMAL => Class::NegNormal,
436 decnumber_sys::DEC_CLASS_NEG_SUBNORMAL => Class::NegSubnormal,
437 decnumber_sys::DEC_CLASS_NEG_ZERO => Class::NegZero,
438 decnumber_sys::DEC_CLASS_POS_ZERO => Class::PosZero,
439 decnumber_sys::DEC_CLASS_POS_SUBNORMAL => Class::PosSubnormal,
440 decnumber_sys::DEC_CLASS_POS_NORMAL => Class::PosNormal,
441 decnumber_sys::DEC_CLASS_POS_INF => Class::PosInfinity,
442 _ => unreachable!("invalid C class value"),
443 }
444 }
445}
446
447impl fmt::Display for Class {
448 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
449 match self {
450 Class::SignalingNan => f.write_str("sNaN"),
451 Class::QuietNan => f.write_str("NaN"),
452 Class::NegInfinity => f.write_str("-Infinity"),
453 Class::NegNormal => f.write_str("-Normal"),
454 Class::NegSubnormal => f.write_str("-Subnormal"),
455 Class::NegZero => f.write_str("-Zero"),
456 Class::PosZero => f.write_str("+Zero"),
457 Class::PosSubnormal => f.write_str("+Subnormal"),
458 Class::PosNormal => f.write_str("+Normal"),
459 Class::PosInfinity => f.write_str("+Infinity"),
460 }
461 }
462}