/* The decNumber package doesn't provide arithmetic for decSingle (32 bits); convert to decDouble, use the operation for that, and convert back. */ static inline _Decimal32 d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b) { union { _Decimal32 c; decSingle f; } a32, b32, res32; decDouble a, b, res; decContext context; /* Widen the operands and perform the operation. */ a32.c = arg_a; b32.c = arg_b; decSingleToWider (&a32.f, &a); decSingleToWider (&b32.f, &b); res = dfp_binary_op (op, a, b); /* Narrow the result, which might result in an underflow or overflow. */ decContextDefault (&context, CONTEXT_INIT); DFP_INIT_ROUNDMODE (context.round); decSingleFromWider (&res32.f, &res, &context); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) { /* decNumber exception flags we care about here. */ int ieee_flags; int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow; dec_flags &= context.status; ieee_flags = DFP_IEEE_FLAGS (dec_flags); if (ieee_flags != 0) DFP_HANDLE_EXCEPTIONS (ieee_flags); } return res32.c; }
/* decFloat operations are supported for decDouble (64 bits) and decQuad (128 bits). The bit patterns for the types are the same. */ static inline DFP_C_TYPE dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { union { DFP_C_TYPE c; decFloat f; } a, b, result; a.c = arg_a; b.c = arg_b; result.f = dfp_binary_op (op, a.f, b.f); return result.c; }
DFP_C_TYPE DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { return dfp_binary_op (decNumberDivide, arg_a, arg_b); }
DFP_C_TYPE DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { return dfp_binary_op (decNumberMultiply, arg_a, arg_b); }
DFP_C_TYPE DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { return dfp_binary_op (decNumberSubtract, arg_a, arg_b); }
DFP_C_TYPE DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { return dfp_binary_op (decNumberAdd, arg_a, arg_b); }