New module to perform decimal floating point arithmetic for charts.
[pspp] / src / math / decimal.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2015 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17
18 #ifndef DECIMAL_H
19 #define DECIMAL_H
20
21 /* This module provides a rudimentary floating point implementation using a decimal
22    base.   It can be used for floating point calculations where it is desirable that
23    the result is representable in decimal base.
24
25    Any of the functions may set the static variable dec_warning to non-zero if a
26    loss of precision or other issue occurs.
27
28    This does not purport to be efficient, either in time or space.
29  */
30
31 #include <stdio.h>
32 #include <stdbool.h>
33
34 #include <limits.h>
35
36 #define DEC_PREC 1 /* operation resulted in a loss of precision */
37 extern int dec_warning;
38
39
40 #define ORDINATE_LONG
41 #define MANTISSA_LONG
42
43 #ifdef ORDINATE_SHORT
44 typedef short ord_t;
45 static const short ORD_MAX = SHRT_MAX;
46 #define PR_ORD "%d"
47 #endif
48
49 #ifdef ORDINATE_INT
50 typedef int ord_t;
51 static const int ORD_MAX = INT_MAX;
52 #define PR_ORD "%d"
53 #endif
54
55 #ifdef ORDINATE_LONG
56 typedef long ord_t;
57 static const long ORD_MAX = LONG_MAX;
58 #define PR_ORD "%ld"
59 #endif
60
61
62
63 #ifdef MANTISSA_SHORT
64 typedef short mant_t;
65 static const short MANT_MAX = SHRT_MAX;
66 #define PR_MANT "%d"
67 #endif
68
69 #ifdef MANTISSA_INT
70 typedef int mant_t;
71 static const int MANT_MAX = INT_MAX;
72 #define PR_MANT "%d"
73 #endif
74
75 #ifdef MANTISSA_LONG
76 typedef long mant_t;
77 static const long MANT_MAX = LONG_MAX;
78 #define PR_MANT "%ld"
79 #endif
80
81
82
83 #define MANT_MIN        (-MANT_MAX - 1)
84 #define ORD_MIN         (-ORD_MAX - 1)
85
86 struct decimal 
87 {
88   ord_t ordinate;
89   mant_t mantissa;
90 };
91
92 void normalise (struct decimal *d1, struct decimal *d2);
93 void decimal_init (struct decimal *dec, ord_t ord, mant_t mant);
94 void decimal_init_from_string (struct decimal *dec, const char *s);
95 int decimal_cmp (const struct decimal *d1, const struct decimal *d2);
96 void decimal_int_multiply (struct decimal *dest, ord_t m);
97 void decimal_int_divide (struct decimal *dest, ord_t m);
98 void decimal_divide (struct decimal *dest, const struct decimal *src);
99 void decimal_show (const struct decimal *dec, FILE *f);
100 char *decimal_to_string (const struct decimal *dec);
101
102 void decimal_add (struct decimal *dest, const struct decimal *);
103 void decimal_subtract (struct decimal *dest, const struct decimal *);
104 ord_t decimal_ceil (const struct decimal *d);
105 ord_t decimal_floor (const struct decimal *d);
106 mant_t dec_log10 (const struct decimal *d);
107
108
109 void decimal_from_double (struct decimal *dec, double x);
110 double decimal_to_double (const struct decimal *dec);
111
112
113
114 #endif