1/*
2 * Legal Notice
3 *
4 * This document and associated source code (the "Work") is a part of a
5 * benchmark specification maintained by the TPC.
6 *
7 * The TPC reserves all right, title, and interest to the Work as provided
8 * under U.S. and international laws, including without limitation all patent
9 * and trademark rights therein.
10 *
11 * No Warranty
12 *
13 * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
14 * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
15 * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
16 * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
17 * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
18 * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
19 * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
20 * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
21 * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
22 * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
23 * WITH REGARD TO THE WORK.
24 * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
25 * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
26 * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
27 * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
28 * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
29 * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
30 * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
31 * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * Contributors:
34 * Gradient Systems
35 */
36
37/*** includes ***/
38#include "config.h"
39#include "porting.h"
40#ifndef USE_STDLIB_H
41#include <malloc.h>
42#endif
43#include <stdio.h>
44#include "decimal.h"
45#include "mathops.h"
46
47/*
48 * Routine: set_precision(decimal_t *dest, int size, int precision)
49 * Purpose:
50 * Algorithm:
51 * Data Structures:
52 *
53 * Params:
54 * Returns: None
55 * Called By:
56 * Calls:
57 * Assumptions:
58 * Side Effects:
59 * TODO: None
60 */
61void set_precision(decimal_t *dest, int scale, int precision) {
62 dest->scale = scale;
63 dest->precision = precision;
64 dest->number = 0;
65 dest->flags = 0;
66
67 return;
68}
69
70/*
71 * Routine: mk_decimal(int size, int precision)
72 * Purpose: initialize a decimal_t
73 * Algorithm:
74 * Data Structures:
75 *
76 * Params: int size: total number of places in the decimal
77 * int precision: number of places in the fraction
78 * Returns: decimal_t *
79 * Called By:
80 * Calls:
81 * Assumptions:
82 * Side Effects:
83 * TODO: None
84 */
85decimal_t *mk_decimal(int s, int p) {
86 decimal_t *res;
87
88 if ((s < 0) || (p < 0))
89 return (NULL);
90
91 res = (decimal_t *)malloc(sizeof(struct DECIMAL_T));
92 MALLOC_CHECK(res);
93
94 res->flags = 0;
95 res->scale = s;
96 res->precision = p;
97 res->flags |= FL_INIT;
98
99 return (res);
100}
101
102/*
103 * Routine: itodec(int src, decimal_t *dest)
104 * Purpose: convert an integer to a decimal_t
105 * Algorithm:
106 * Data Structures:
107 *
108 * Params: source integer
109 * Returns: decimal_t *
110 * Called By:
111 * Calls:
112 * Assumptions:
113 * Side Effects:
114 * TODO:
115 * 20000104 need to set errno on error
116 */
117int itodec(decimal_t *dest, int src) {
118 int scale = 1, bound = 1;
119
120 while ((bound * 10) <= src) {
121 scale += 1;
122 bound *= 10;
123 }
124
125 dest->precision = 0;
126 dest->scale = scale;
127 dest->number = src;
128
129 return (0);
130}
131
132/*
133 * Routine: ftodec(double f, decimal_t *dec)
134 * Purpose: Convert a double to a decimal_t
135 * Algorithm:
136 * Data Structures:
137 *
138 * Params: double f
139 * Returns: decimal_t *
140 * Called By:
141 * Calls:
142 * Assumptions:
143 * Side Effects:
144 * TODO: None
145 */
146int ftodec(decimal_t *dest, double f) {
147 static char valbuf[20];
148
149 sprintf(valbuf, "%f", f);
150
151 return (strtodec(dest, valbuf));
152}
153
154/*
155 * Routine: strtodec()
156 * Purpose: Convert an ascii string to a decimal_t structure
157 * Algorithm:
158 * Data Structures:
159 *
160 * Params: char *s
161 * Returns: decimal_t *
162 * Called By:
163 * Calls:
164 * Assumptions:
165 * Side Effects:
166 * TODO: None
167 */
168int strtodec(decimal_t *dest, char *s) {
169 int i;
170 char *d_pt;
171 char valbuf[20];
172
173 strcpy(valbuf, s);
174 dest->flags = 0;
175 if ((d_pt = strchr(valbuf, '.')) == NULL) {
176 dest->scale = strlen(valbuf);
177 dest->number = atoi(valbuf);
178 dest->precision = 0;
179 } else {
180 *d_pt = '\0';
181 d_pt += 1;
182 dest->scale = strlen(valbuf);
183 dest->number = atoi(valbuf);
184 dest->precision = strlen(d_pt);
185 for (i = 0; i < dest->precision; i++)
186 dest->number *= 10;
187 dest->number += atoi(d_pt);
188 }
189
190 if (*s == '-' && dest->number > 0)
191 dest->number *= -1;
192
193 return (0);
194}
195
196/*
197 * Routine: dectostr(decimal_t *d, char *buf)
198 * Purpose: convert a decimal structure to a string
199 * Algorithm:
200 * Data Structures:
201 *
202 * Params:
203 * Returns: char *; NULL on success
204 * Called By:
205 * Calls:
206 * Assumptions:
207 * Side Effects:
208 * TODO: None
209 */
210int dectostr(char *dest, decimal_t *d) {
211 ds_key_t number;
212 int i;
213 static int bInit = 0;
214 static char szFormat[20];
215
216 if (!bInit) {
217 sprintf(szFormat, "%s.%s", HUGE_FORMAT, HUGE_FORMAT);
218 bInit = 1;
219 }
220
221 if (d == NULL || dest == NULL)
222 return (-1);
223 for (number = d->number, i = 0; i < d->precision; i++)
224 number /= 10;
225
226 sprintf(dest, szFormat, number, d->number - number);
227
228 return (0);
229}
230
231/*
232 * Routine: dectof(float *dest, decimal_t *d)
233 * Purpose: convert a decimal structure to a double
234 * Algorithm:
235 * Data Structures:
236 *
237 * Params:
238 * Returns: char *; NULL on success
239 * Called By:
240 * Calls:
241 * Assumptions:
242 * Side Effects:
243 * TODO: None
244 */
245int dectoflt(double *dest, decimal_t *d) {
246 if ((dest == NULL) || (d == NULL))
247 return (-1);
248#ifdef WIN32
249#pragma warning(disable : 4244)
250#endif
251 *dest = d->number;
252#ifdef WIN32
253#pragma warning(default : 4244)
254#endif
255 while (--d->precision > 0)
256 *dest /= 10.0;
257
258 return (0);
259}
260
261/*
262 * Routine: decimal_t_op(int op, decimal_t *operand1, decimal_t *operand2)
263 * Purpose: execute arbitrary binary operations on decimal_t's
264 * Algorithm:
265 * Data Structures:
266 *
267 * Params:
268 * Returns:
269 * Called By:
270 * Calls:
271 * Assumptions:
272 * Side Effects:
273 * TODO: None
274 */
275int decimal_t_op(decimal_t *dest, int op, decimal_t *d1, decimal_t *d2) {
276 int res, np;
277 float f1, f2;
278
279 if ((d1 == NULL) || (d2 == NULL))
280 return (-1);
281
282 dest->scale = (d1->scale > d2->scale) ? d1->scale : d2->scale;
283 if (d1->precision > d2->precision) {
284 dest->precision = d1->precision;
285 } else {
286 dest->precision = d2->precision;
287 }
288
289 switch (op) {
290 case OP_PLUS:
291 dest->number = d1->number + d2->number;
292 break;
293 case OP_MINUS:
294 dest->number = d1->number - d2->number;
295 break;
296 case OP_MULT:
297 res = d1->precision + d2->precision;
298 dest->number = d1->number * d2->number;
299 while (res-- > dest->precision)
300 dest->number /= 10;
301 break;
302 case OP_DIV:
303 f1 = (float)d1->number;
304 np = d1->precision;
305 while (np < dest->precision) {
306 f1 *= 10.0;
307 np += 1;
308 }
309 np = 0;
310 while (np < dest->precision) {
311 f1 *= 10.0;
312 np += 1;
313 }
314 f2 = (float)d2->number;
315 np = d2->precision;
316 while (np < dest->precision) {
317 f2 *= 10.0;
318 np += 1;
319 }
320
321 dest->number = (int)(f1 / f2);
322 break;
323 default:
324 printf("decimal_t_op does not support op %d\n", op);
325 exit(1);
326 break;
327 }
328
329 return (0);
330}
331
332#ifdef TEST
333main() {
334 decimal_t *res;
335 int code;
336
337 /* mk_decimal */
338 res = mk_decimal(5, 2);
339 if (res == NULL) {
340 printf("mk_decimal returned NULL\n");
341 exit(-1);
342 }
343
344 /* itodec */
345 itodec(res, 0);
346 code = dectoi(res);
347 if (code) {
348 printf("r_decimal:itodec(0, res) != 0 (%d)\n", code);
349 exit(-1);
350 }
351
352 itodec(res, 999);
353 code = dectoi(res);
354 if (code != 999) {
355 printf("r_decimal:itodec(999, res) != 0 (%d)\n", code);
356 exit(-1);
357 }
358
359 exit(0);
360}
361#endif /* TEST */
362