Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Modules/_decimal/libmpdec/context.c
12 views
1
/*
2
* Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
*
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
*
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
29
#include "mpdecimal.h"
30
31
#include <signal.h>
32
#include <stdio.h>
33
#include <string.h>
34
35
36
void
37
mpd_dflt_traphandler(mpd_context_t *ctx)
38
{
39
(void)ctx;
40
raise(SIGFPE);
41
}
42
43
void (* mpd_traphandler)(mpd_context_t *) = mpd_dflt_traphandler;
44
45
46
/* Set guaranteed minimum number of coefficient words. The function may
47
be used once at program start. Setting MPD_MINALLOC to out-of-bounds
48
values is a catastrophic error, so in that case the function exits rather
49
than relying on the user to check a return value. */
50
void
51
mpd_setminalloc(mpd_ssize_t n)
52
{
53
static int minalloc_is_set = 0;
54
55
if (minalloc_is_set) {
56
mpd_err_warn("mpd_setminalloc: ignoring request to set "
57
"MPD_MINALLOC a second time\n");
58
return;
59
}
60
if (n < MPD_MINALLOC_MIN || n > MPD_MINALLOC_MAX) {
61
mpd_err_fatal("illegal value for MPD_MINALLOC"); /* GCOV_NOT_REACHED */
62
}
63
MPD_MINALLOC = n;
64
minalloc_is_set = 1;
65
}
66
67
void
68
mpd_init(mpd_context_t *ctx, mpd_ssize_t prec)
69
{
70
mpd_ssize_t ideal_minalloc;
71
72
mpd_defaultcontext(ctx);
73
74
if (!mpd_qsetprec(ctx, prec)) {
75
mpd_addstatus_raise(ctx, MPD_Invalid_context);
76
return;
77
}
78
79
ideal_minalloc = 2 * ((prec+MPD_RDIGITS-1) / MPD_RDIGITS);
80
if (ideal_minalloc < MPD_MINALLOC_MIN) ideal_minalloc = MPD_MINALLOC_MIN;
81
if (ideal_minalloc > MPD_MINALLOC_MAX) ideal_minalloc = MPD_MINALLOC_MAX;
82
83
mpd_setminalloc(ideal_minalloc);
84
}
85
86
void
87
mpd_maxcontext(mpd_context_t *ctx)
88
{
89
ctx->prec=MPD_MAX_PREC;
90
ctx->emax=MPD_MAX_EMAX;
91
ctx->emin=MPD_MIN_EMIN;
92
ctx->round=MPD_ROUND_HALF_EVEN;
93
ctx->traps=MPD_Traps;
94
ctx->status=0;
95
ctx->newtrap=0;
96
ctx->clamp=0;
97
ctx->allcr=1;
98
}
99
100
void
101
mpd_defaultcontext(mpd_context_t *ctx)
102
{
103
ctx->prec=2*MPD_RDIGITS;
104
ctx->emax=MPD_MAX_EMAX;
105
ctx->emin=MPD_MIN_EMIN;
106
ctx->round=MPD_ROUND_HALF_UP;
107
ctx->traps=MPD_Traps;
108
ctx->status=0;
109
ctx->newtrap=0;
110
ctx->clamp=0;
111
ctx->allcr=1;
112
}
113
114
void
115
mpd_basiccontext(mpd_context_t *ctx)
116
{
117
ctx->prec=9;
118
ctx->emax=MPD_MAX_EMAX;
119
ctx->emin=MPD_MIN_EMIN;
120
ctx->round=MPD_ROUND_HALF_UP;
121
ctx->traps=MPD_Traps|MPD_Clamped;
122
ctx->status=0;
123
ctx->newtrap=0;
124
ctx->clamp=0;
125
ctx->allcr=1;
126
}
127
128
int
129
mpd_ieee_context(mpd_context_t *ctx, int bits)
130
{
131
if (bits <= 0 || bits > MPD_IEEE_CONTEXT_MAX_BITS || bits % 32) {
132
return -1;
133
}
134
135
ctx->prec = 9 * (bits/32) - 2;
136
ctx->emax = 3 * ((mpd_ssize_t)1<<(bits/16+3));
137
ctx->emin = 1 - ctx->emax;
138
ctx->round=MPD_ROUND_HALF_EVEN;
139
ctx->traps=0;
140
ctx->status=0;
141
ctx->newtrap=0;
142
ctx->clamp=1;
143
ctx->allcr=1;
144
145
return 0;
146
}
147
148
mpd_ssize_t
149
mpd_getprec(const mpd_context_t *ctx)
150
{
151
return ctx->prec;
152
}
153
154
mpd_ssize_t
155
mpd_getemax(const mpd_context_t *ctx)
156
{
157
return ctx->emax;
158
}
159
160
mpd_ssize_t
161
mpd_getemin(const mpd_context_t *ctx)
162
{
163
return ctx->emin;
164
}
165
166
int
167
mpd_getround(const mpd_context_t *ctx)
168
{
169
return ctx->round;
170
}
171
172
uint32_t
173
mpd_gettraps(const mpd_context_t *ctx)
174
{
175
return ctx->traps;
176
}
177
178
uint32_t
179
mpd_getstatus(const mpd_context_t *ctx)
180
{
181
return ctx->status;
182
}
183
184
int
185
mpd_getclamp(const mpd_context_t *ctx)
186
{
187
return ctx->clamp;
188
}
189
190
int
191
mpd_getcr(const mpd_context_t *ctx)
192
{
193
return ctx->allcr;
194
}
195
196
197
int
198
mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec)
199
{
200
if (prec <= 0 || prec > MPD_MAX_PREC) {
201
return 0;
202
}
203
ctx->prec = prec;
204
return 1;
205
}
206
207
int
208
mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax)
209
{
210
if (emax < 0 || emax > MPD_MAX_EMAX) {
211
return 0;
212
}
213
ctx->emax = emax;
214
return 1;
215
}
216
217
int
218
mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin)
219
{
220
if (emin > 0 || emin < MPD_MIN_EMIN) {
221
return 0;
222
}
223
ctx->emin = emin;
224
return 1;
225
}
226
227
int
228
mpd_qsetround(mpd_context_t *ctx, int round)
229
{
230
if (!(0 <= round && round < MPD_ROUND_GUARD)) {
231
return 0;
232
}
233
ctx->round = round;
234
return 1;
235
}
236
237
int
238
mpd_qsettraps(mpd_context_t *ctx, uint32_t flags)
239
{
240
if (flags > MPD_Max_status) {
241
return 0;
242
}
243
ctx->traps = flags;
244
return 1;
245
}
246
247
int
248
mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags)
249
{
250
if (flags > MPD_Max_status) {
251
return 0;
252
}
253
ctx->status = flags;
254
return 1;
255
}
256
257
int
258
mpd_qsetclamp(mpd_context_t *ctx, int c)
259
{
260
if (c != 0 && c != 1) {
261
return 0;
262
}
263
ctx->clamp = c;
264
return 1;
265
}
266
267
int
268
mpd_qsetcr(mpd_context_t *ctx, int c)
269
{
270
if (c != 0 && c != 1) {
271
return 0;
272
}
273
ctx->allcr = c;
274
return 1;
275
}
276
277
278
void
279
mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags)
280
{
281
ctx->status |= flags;
282
if (flags&ctx->traps) {
283
ctx->newtrap = (flags&ctx->traps);
284
mpd_traphandler(ctx);
285
}
286
}
287
288