1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2016-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8%%	header
9
10/**	@file	dk4maai16.h	Operations on int16_t data.
11
12	CRT on Windows: Optional.
13*/
14
15
16#ifndef DK4CONF_H_INCLUDED
17#if DK4_BUILDING_DKTOOLS4
18#include "dk4conf.h"
19#else
20#include <dktools-4/dk4conf.h>
21#endif
22#endif
23
24#ifndef DK4ERROR_H_INCLUDED
25#if DK4_BUILDING_DKTOOLS4
26#include <libdk4base/dk4error.h>
27#else
28#include <dktools-4/dk4error.h>
29#endif
30#endif
31
32#if DK4_HAVE_STDLIB_H
33#ifndef	DK4_STDLIB_H_INCLUDED
34#include <stdlib.h>
35#define	DK4_STDLIB_H_INCLUDED 1
36#endif
37#endif
38
39#if DK4_HAVE_SYS_TYPES_H
40#ifndef	DK4_SYS_TYPES_H_INCLUDED
41#include <sys/types.h>
42#define	DK4_SYS_TYPES_H_INCLUDED 1
43#endif
44#endif
45
46#if DK4_HAVE_STDINT_H
47#ifndef	DK4_STDINT_H_INCLUDED
48#include <stdint.h>
49#define	DK4_STDINT_H_INCLUDED 1
50#endif
51#endif
52
53#ifndef	INT16_MAX
54#define	INT16_MAX	((int16_t)32767)
55#endif
56
57#ifndef	INT16_MIN
58#define	INT16_MIN	(((int16_t)(-32767)) - ((int16_t)1))
59#endif
60
61#ifdef	__cplusplus
62extern "C" {
63#endif
64
65/**	Addition of int16_t.
66	@param	a	Left operand.
67	@param	b	Right operand.
68	@param	erp	Error report, may be NULL.
69	@return	Operation result.
70
71	Error codes:
72	- DK4_E_INVALID_ARGUMENTS<br>
73	  if a or b is out of range
74	- DK4_E_MATH_OVERFLOW<br>
75	  if a mathematical overfow occured.
76*/
77int16_t
78dk4ma_int16_t_add(int16_t a, int16_t b, dk4_er_t *erp);
79
80/**	Substraction of int16_t.
81	@param	a	Left operand.
82	@param	b	Right operand.
83	@param	erp	Error report, may be NULL.
84	@return	Operation result.
85
86	Error codes:
87	- DK4_E_INVALID_ARGUMENTS<br>
88	  if a or b is out of range
89	- DK4_E_MATH_OVERFLOW<br>
90	  if a mathematical overfow occured.
91*/
92int16_t
93dk4ma_int16_t_sub(int16_t a, int16_t b, dk4_er_t *erp);
94
95/**	Multiplication of int16_t.
96	@param	a	Left operand.
97	@param	b	Right operand.
98	@param	erp	Error report, may be NULL.
99	@return	Operation result.
100
101	Error codes:
102	- DK4_E_INVALID_ARGUMENTS<br>
103	  if a or b is out of range
104	- DK4_E_MATH_OVERFLOW<br>
105	  if a mathematical overfow occured.
106*/
107int16_t
108dk4ma_int16_t_mul(int16_t a, int16_t b, dk4_er_t *erp);
109
110/**	Division of int16_t.
111	@param	a	Left operand.
112	@param	b	Right operand.
113	@param	erp	Error report, may be NULL.
114	@return	Operation result.
115
116	Error codes:
117	- DK4_E_INVALID_ARGUMENTS<br>
118	  if a or b is out of range
119	- DK4_E_MATH_OVERFLOW<br>
120	  if a mathematical overfow occured,
121	- DK4_E_MATH_DIVZERO<br>
122	  if b is 0.
123*/
124int16_t
125dk4ma_int16_t_div(int16_t a, int16_t b, dk4_er_t *erp);
126
127/**	Absolute value.
128	@param	a	Argument.
129	@param	erp	Error report, may be NULL.
130	@return	Absolute value of a.
131
132	Error codes:
133	- DK4_E_INVALID_ARGUMENTS<br>
134	  if a or b is out of range
135	- DK4_E_MATH_OVERFLOW<br>
136	  if a mathematical overfow occured.
137*/
138int16_t
139dk4ma_int16_t_abs(int16_t a, dk4_er_t *erp);
140
141/**	Convert dk4_im_t value to int16_t.
142	@param	i	Value to convert.
143	@param	erp	Error report, may be NULL.
144	@return	Conversion result.
145
146	Error codes: DK4_E_MATH_OVERFLOW.
147*/
148int16_t
149dk4ma_int16_from(dk4_im_t i, dk4_er_t *erp);
150
151/**	Convert double to int16_t.
152	@param	d	Value to convert.
153	@param	erp	Error report, may be NULL.
154	@return	Conversion result.
155
156	Error codes: DK4_E_OVERFLOW.
157*/
158int16_t
159dk4ma_int16_from_double(double d, dk4_er_t *erp);
160
161#ifdef	__cplusplus
162}
163#endif
164
165
166%%	module
167
168#include "dk4conf.h"
169#include <libdk4ma/dk4maai16.h>
170
171
172
173$!trace-include
174
175
176
177int16_t
178dk4ma_int16_t_add(int16_t a, int16_t b, dk4_er_t *erp)
179{
180  if ((0 < a) && (0 < b)) {
181    if ((DK4_I16_MAX - a) < b) {
182      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
183    }
184  } else {
185    if ((0 > a) && (0 > b)) {
186      if (DK4_I16_MIN == a) {
187        dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
188      } else {
189        if ((DK4_I16_MIN - a) > b) {
190	  dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
191	}
192      }
193    }
194  }
195  return ((int16_t)(a + b));
196}
197
198
199
200int16_t
201dk4ma_int16_t_sub(int16_t a, int16_t b, dk4_er_t *erp)
202{
203  if ((0 < a) && (0 > b)) {
204    if ((DK4_I16_MAX + b) < a) {
205      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
206    }
207  } else {
208    if ((0 > a) && (0 < b)) {
209      if ((DK4_I16_MIN + b) > a) {
210        dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
211      }
212    }
213  }
214  return ((int16_t)(a - b));
215}
216
217
218
219int16_t
220dk4ma_int16_t_mul(int16_t a, int16_t b, dk4_er_t *erp)
221{
222  if ((0 != a) && (0 != b)) {
223    if (DK4_I16_MIN == b) {
224      if (1 != a) {
225        dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
226      }
227    } else {
228      if (DK4_I16_MIN == a) {
229        if (1 != b) {
230	  dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
231	}
232      } else {
233        if (0 < a) {
234	  if (0 < b) {
235	    if ((DK4_I16_MAX / a) < b) {
236	      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
237	    }
238	  } else {
239	    if ((DK4_I16_MIN / a) > b) {
240	      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
241	    }
242	  }
243	} else {
244	  if (0 < b) {
245	    if ((DK4_I16_MIN / b) > a) {
246	      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
247	    }
248	  } else {
249	    if ((DK4_I16_MAX / (0 - a)) < (0 - b)) {
250	      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
251	    }
252	  }
253	}
254      }
255    }
256  }
257  return ((int16_t)(a * b));
258}
259
260
261
262int16_t
263dk4ma_int16_t_div(int16_t a, int16_t b, dk4_er_t *erp)
264{
265  int16_t	back	= 0;
266
267  if (0 != b) {
268    if ((DK4_I16_MIN == a) && (-1 == b)) {
269      back = DK4_I16_MAX;
270      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
271    } else {
272      back = (int16_t)(a / b);
273    }
274  } else {
275    if (0 < a) {
276      back = DK4_I16_MAX;
277    } else {
278      if (0 > a) {
279        back = DK4_I16_MIN;
280      }
281    }
282    dk4error_set_simple_error_code(erp, DK4_E_MATH_DIVZERO);
283  }
284  return back;
285}
286
287
288
289int16_t
290dk4ma_int16_t_abs(int16_t a, dk4_er_t *erp)
291{
292  if (DK4_I16_MIN != a) {
293    if ((int16_t)0 > a) {
294      return ((int16_t)(0 - a));
295    } else {
296      return a;
297    }
298  } else {
299    dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
300    return (DK4_I16_MAX);
301  }
302}
303
304
305
306int16_t
307dk4ma_int16_from(dk4_im_t i, dk4_er_t *erp)
308{
309	if (((dk4_im_t)(DK4_I16_MAX) < i) || ((dk4_im_t)(DK4_I16_MIN) > i)) {
310		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
311	}
312	return ((int16_t)i);
313}
314
315
316
317int16_t
318dk4ma_int16_from_double(double d, dk4_er_t *erp)
319{
320	int16_t back	= 0;
321	if ((double)(DK4_I16_MIN) > d) {
322		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
323		back = DK4_I16_MIN;
324	}
325	else {
326		if ((double)(DK4_I16_MAX) < d) {
327			dk4error_set_simple_error_code(erp,DK4_E_MATH_OVERFLOW);
328			back = DK4_I16_MAX;
329		}
330		else {
331			back = (int16_t)d;
332		}
333	}
334	return back;
335}
336
337