File: dimath_internal.h

package info (click to toggle)
di 6.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 856 kB
  • sloc: ansic: 9,271; sh: 5,090; perl: 1,749; awk: 463; makefile: 371
file content (226 lines) | stat: -rw-r--r-- 3,978 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/* Copyright 2025 Brad Lanam Pleasant Hill CA */

#ifndef INC_DIMATH_INTERNAL_H
#define INC_DIMATH_INTERNAL_H

#include "config.h"

#if _hdr_stdio
# include <stdio.h>
#endif
#if _hdr_stddef
# include <stddef.h>
#endif

#include "dimath.h"

// # pragma clang diagnostic push
// # pragma clang diagnostic ignored "-Wbad-function-cast"

# if defined (__cplusplus) || defined (c_plusplus)
extern "C" {
# endif

/* a double has a longer mantissa than an unsigned int, */
/* but the accuracy may be less. */
#if _siz_long_double > 8
  typedef long double di_unum_t;
  typedef long double di_snum_t;
# define DI_INTERNAL_DOUBLE
#elif _siz_double == 8
  typedef double di_unum_t;
  typedef double di_snum_t;
# define DI_INTERNAL_DOUBLE
#elif _siz_uint64_t == 8
  typedef uint64_t di_unum_t;
  typedef int64_t di_snum_t;
# define DI_INTERNAL_INT
#elif _siz_long == 8
  typedef unsigned long di_unum_t;
  typedef long di_snum_t;
# define DI_INTERNAL_INT
#elif _siz_long_long == 8
  typedef unsigned long long di_unum_t;
  typedef long long di_snum_t;
# define DI_INTERNAL_INT
#elif _siz_long == 4
  typedef unsigned long di_unum_t;
  typedef long di_snum_t;
# define DI_INTERNAL_INT
#else
# error "unable to locate a valid type"
#endif

typedef di_unum_t dinum_t;

static inline void
dinum_init (dinum_t *r)
{
  *r = 0;
}

static inline void
dinum_clear (dinum_t *r)
{
}

static inline void
dinum_str (const dinum_t *r, char *str, Size_t sz)
{
#if defined (DI_INTERNAL_DOUBLE)
# if _siz_long_double > 8
  Snprintf1 (str, sz, "%.0Lf", *r);
# else
  Snprintf1 (str, sz, "%.0f", *r);
# endif
#else
# if _hdr_inttypes && _siz_uint64_t == 8
  Snprintf1 (str, sz, "%" PRIu64, *r);
# elif _siz_long == 8
  Snprintf1 (str, sz, "%ld", *r);
# elif _siz_long_long == 8
  Snprintf1 (str, sz, "%lld", *r);
# else
  Snprintf1 (str, sz, "%d", *r);
# endif
#endif
}

static inline void
dinum_set (dinum_t *r, const dinum_t *val)
{
  *r = *val;
}

static inline void
dinum_set_u (dinum_t *r, di_ui_t val)
{
  *r = (dinum_t) val;
}

static inline void
dinum_set_s (dinum_t *r, di_si_t val)
{
  *r = (dinum_t) val;
}

static inline void
dinum_add_u (dinum_t *r, di_ui_t val)
{
  *r += (dinum_t) val;
}

static inline void
dinum_add (dinum_t *r, const dinum_t *val)
{
  *r += *val;
}

static inline void
dinum_sub_u (dinum_t *r, di_ui_t val)
{
  *r -= (dinum_t) val;
}

static inline void
dinum_sub (dinum_t *r, const dinum_t *val)
{
  *r -= *val;
}

static inline int
dinum_cmp (const dinum_t *r, const dinum_t *val)
{
  int     rc = 0;

  if (*r < *val) {
    rc = -1;
  } else if (*r > *val) {
    rc = 1;
  }
  return rc;
}

static inline int
dinum_cmp_s (const dinum_t *r, di_si_t val)
{
  di_snum_t   t;
  int         rc = 0;

  t = (di_snum_t) *r;
  if (t < val) {
    rc = -1;
  } else if (t > val) {
    rc = 1;
  }
  return rc;
}

static inline void
dinum_mul (dinum_t *r, const dinum_t *val)
{
  *r *= *val;
}

static inline void
dinum_mul_u (dinum_t *r, di_ui_t val)
{
  *r *= (dinum_t) val;
}

static inline void
dinum_mul_uu (dinum_t *r, di_ui_t vala, di_ui_t valb)
{
  *r = (dinum_t) vala;
  *r *= (dinum_t) valb;
}

static inline double
dinum_scale (dinum_t *r, dinum_t *val)
{
  double    dval;

# if defined (DI_INTERNAL_INT)
  dinum_t   t;

  if (*val == 0) {
    return 0.0;
  }
  t = (*r * DI_SCALE_PREC) / *val;
  dval = (double) t;
  dval /= (double) DI_SCALE_PREC;
# endif
# if defined (DI_INTERNAL_DOUBLE)
  if (*val == (dinum_t) 0.0) {
    return (dinum_t) 0.0;
  }
  dval = (double) (*r / *val);
# endif

  return dval;
}

static inline double
dinum_perc (dinum_t *r, dinum_t *val)
{
  double      dval = 0.0;

#if defined (DI_INTERNAL_DOUBLE)
  dval = (double) (*r / *val);
#endif
#if defined (DI_INTERNAL_INT)
  /* in the case of a uint, simply convert and divide */
  dval = (double) *r / (double) *val;
#endif
  dval *= 100.0;

  return dval;
}

// # pragma clang diagnostic pop

# if defined (__cplusplus) || defined (c_plusplus)
}
# endif

#endif /* INC_DIMATH_INTERNAL_H */