1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2015-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8
9%%	header
10
11/**	@file
12	Arithmetic operations on unsigned long.
13
14	CRT on Windows: Optional.
15*/
16
17#ifndef DK4CONF_H_INCLUDED
18#if DK4_BUILDING_DKTOOLS4
19#include "dk4conf.h"
20#else
21#include <dktools-4/dk4conf.h>
22#endif
23#endif
24
25#ifndef DK4TYPES_H_INCLUDED
26#if DK4_BUILDING_DKTOOLS4
27#include <libdk4base/dk4types.h>
28#else
29#include <dktools-4/dk4types.h>
30#endif
31#endif
32
33#ifndef DK4ERROR_H_INCLUDED
34#if DK4_BUILDING_DKTOOLS4
35#include <libdk4base/dk4error.h>
36#else
37#include <dktools-4/dk4error.h>
38#endif
39#endif
40
41
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/**	Addition.
48        @param	a	Left operand.
49        @param	b	Right operand.
50        @param	erp	Error report, may be NULL.
51        @return	Result on success, least significant result bits
52        on overflow (see ec component of erp).
53
54	Error codes: DK4_E_OVERFLOW.
55*/
56unsigned long
57dk4ma_ulong_add(unsigned long a, unsigned long b, dk4_er_t *erp);
58
59/**	Subtraction.
60        @param	a	Left operand.
61        @param	b	Right operand.
62        @param	erp	Error report, may be NULL.
63        @return	Result on success, least significant result bits
64        on overflow (see ec component of erp).
65
66	Error codes: DK4_E_OVERFLOW.
67*/
68unsigned long
69dk4ma_ulong_sub(unsigned long a, unsigned long b, dk4_er_t *erp);
70
71/**	Multiplication.
72        @param	a	Left factor.
73        @param	b	right factor.
74        @param	erp	Error report, may be NULL.
75        @return	Result on success, least significant
76        bits on overflow (see ec component of erp).
77
78	Error codes: DK4_E_OVERFLOW.
79*/
80unsigned long
81dk4ma_ulong_mul(unsigned long a, unsigned long b, dk4_er_t *erp);
82
83/**	Division.
84        @param	a	Counter (left operand).
85        @param	b	Denominator (right operand).
86        @param	erp	Error report, may be NULL.
87        @return	Division result on success,
88        ULONG_MAX on division by zero
89        (see the ec component of erp).
90
91	Error codes: DK4_E_MATH_DIVZERO.
92*/
93unsigned long
94dk4ma_ulong_div(unsigned long a, unsigned long b, dk4_er_t *erp);
95
96/**	Convert dk4_um_t value to unsigned long.
97	@param	u	Value to convert.
98	@param	erp	Error report, may be NULL.
99	@return	Conversion result.
100
101	Error codes: DK4_E_MATH_OVERFLOW.
102*/
103unsigned long
104dk4ma_ulong_from(dk4_um_t u, dk4_er_t *erp);
105
106/**	Convert double to signed char.
107	@param	d	Value to convert.
108	@param	erp	Error report, may be NULL.
109	@return	Conversion result.
110
111	Error codes: DK4_E_OVERFLOW.
112*/
113unsigned long
114dk4ma_ulong_from_double(double d, dk4_er_t *erp);
115
116#ifdef __cplusplus
117}
118#endif
119
120
121%%	module
122
123#include "dk4conf.h"
124#include <libdk4base/dk4types.h>
125#include <libdk4base/dk4error.h>
126#include <libdk4base/dk4numco.h>
127#include <libdk4ma/dk4maaul.h>
128
129
130
131$!trace-include
132
133
134
135unsigned long
136dk4ma_ulong_add(unsigned long a, unsigned long b, dk4_er_t *erp)
137{
138  $? "+ dk4ma_ulong_add %lu %lu", a, b
139  $? ". ULONG_MAX = %lu", ULONG_MAX
140  $? ". ULONG_MAX - a = %lu", (ULONG_MAX - a)
141  $? ". b = %lu", b
142  if ((ULONG_MAX - a) < b) {	$? "! overflow"
143    dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
144  }
145  $? "- dk4ma_ulong_add %lu", (a+b)
146  return (a + b);
147}
148
149
150
151unsigned long
152dk4ma_ulong_sub(unsigned long a, unsigned long b, dk4_er_t *erp)
153{
154  if (b > a) {
155    dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
156  }
157  return (a - b);
158}
159
160
161
162unsigned long
163dk4ma_ulong_mul(unsigned long a, unsigned long b, dk4_er_t *erp)
164{
165  if (0UL < a) {
166    if ((ULONG_MAX / a) < b) {
167      dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
168    }
169  }
170  return (a * b);
171}
172
173
174
175unsigned long
176dk4ma_ulong_div(unsigned long a, unsigned long b, dk4_er_t *erp)
177{
178  if (0UL < b) {
179    return (a / b);
180  } else {
181    dk4error_set_simple_error_code(erp, DK4_E_MATH_DIVZERO);
182    return (unsigned long)(ULONG_MAX);
183  }
184}
185
186
187
188unsigned long
189dk4ma_ulong_from(dk4_um_t u, dk4_er_t *erp)
190{
191	if ((dk4_um_t)(ULONG_MAX) < u) {
192		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
193	}
194	return ((unsigned long)u);
195}
196
197
198
199unsigned long
200dk4ma_ulong_from_double(double d, dk4_er_t *erp)
201{
202	unsigned long	back	= 0UL;
203	if ((double)(ULONG_MAX) < d) {
204		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
205		back = ULONG_MAX;
206	}
207	else {
208		if (0.0 > d) {
209			dk4error_set_simple_error_code(erp,DK4_E_MATH_OVERFLOW);
210		}
211		else {
212			back = (unsigned long)d;
213		}
214	}
215	return  back;
216}
217
218
219