1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2015-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8%% header 9 10/** @file 11 Arithmetic operations on long. 12 13 CRT on Windows: Optional. 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 DK4TYPES_H_INCLUDED 25#if DK4_BUILDING_DKTOOLS4 26#include <libdk4base/dk4types.h> 27#else 28#include <dktools-4/dk4types.h> 29#endif 30#endif 31 32#ifndef DK4ERROR_H_INCLUDED 33#if DK4_BUILDING_DKTOOLS4 34#include <libdk4base/dk4error.h> 35#else 36#include <dktools-4/dk4error.h> 37#endif 38#endif 39 40 41 42#ifdef __cplusplus 43extern "C" { 44#endif 45 46/** Absolute value. 47 @param a Operand. 48 @param erp Error report, may be NULL. 49 @return Result on success, LONG_MAX if a is LONG_MIN 50 (overflow is reported in erp). 51 52 Error codes: DK4_E_OVERFLOW. 53*/ 54long 55dk4ma_long_abs(long a, dk4_er_t *erp); 56 57/** Addition. 58 @param a Left operand. 59 @param b Right operand. 60 @param erp Error report, may be NULL. 61 @return Result on success, least significant result bits 62 on overflow (see ec component of erp). 63 64 Error codes: DK4_E_OVERFLOW. 65*/ 66long 67dk4ma_long_add(long a, long b, dk4_er_t *erp); 68 69/** Subtraction. 70 @param a Left operand. 71 @param b Right operand. 72 @param erp Error report, may be NULL. 73 @return Result on success, least significant result bits 74 on overflow (see ec component of erp). 75 76 Error codes: DK4_E_OVERFLOW. 77*/ 78long 79dk4ma_long_sub(long a, long b, dk4_er_t *erp); 80 81/** Multiplication. 82 @param a Left factor. 83 @param b right factor. 84 @param erp Error report, may be NULL. 85 @return Result on success, least significant 86 bits on overflow (see ec component of erp). 87 88 Error codes: DK4_E_OVERFLOW. 89*/ 90long 91dk4ma_long_mul(long a, long b, dk4_er_t *erp); 92 93/** Division. 94 @param a Counter (left operand). 95 @param b Denominator (right operand). 96 @param erp Error report, may be NULL. 97 @return Division result on success, 98 LONG_MIN, LONG_MAX, or 0 on division by zero or overflow 99 (see the ec component of erp). 100 101 Error codes: DK4_E_OVERFLOW, DK4_E_DIVZERO. 102*/ 103long 104dk4ma_long_div(long a, long b, dk4_er_t *erp); 105 106/** Convert dk4_im_t value to long. 107 @param i Value to convert. 108 @param erp Error report, may be NULL. 109 @return Conversion result. 110 111 Error codes: DK4_E_OVERFLOW. 112*/ 113long 114dk4ma_long_from(dk4_im_t i, dk4_er_t *erp); 115 116/** Convert double to long. 117 @param d Value to convert. 118 @param erp Error report, may be NULL. 119 @return Conversion result. 120 121 Error codes: DK4_E_OVERFLOW. 122*/ 123long 124dk4ma_long_from_double(double d, dk4_er_t *erp); 125 126#ifdef __cplusplus 127} 128#endif 129 130 131%% module 132 133#include "dk4conf.h" 134#include <libdk4base/dk4types.h> 135#include <libdk4base/dk4error.h> 136#include <libdk4base/dk4numco.h> 137#include <libdk4ma/dk4maal.h> 138 139 140 141long 142dk4ma_long_abs(long a, dk4_er_t *erp) 143{ 144 if (LONG_MIN == a) { 145 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 146 } 147 return ((0L <= a) ? a : ((LONG_MIN == a) ? LONG_MAX : (0L - a))); 148} 149 150 151 152long 153dk4ma_long_add(long a, long b, dk4_er_t *erp) 154{ 155 if ((0L < a) && (0L < b)) { 156 if ((LONG_MAX - a) < b) { 157 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 158 } 159 } else { 160 if ((0L > a) && (0L > b)) { 161 if (LONG_MIN == a) { 162 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 163 } else { 164 if ((LONG_MIN - a) > b) { 165 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 166 } 167 } 168 } 169 } 170 return (a + b); 171} 172 173 174 175long 176dk4ma_long_sub(long a, long b, dk4_er_t *erp) 177{ 178 if ((0L < a) && (0L > b)) { 179 if ((LONG_MAX + b) < a) { 180 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 181 } 182 } else { 183 if ((0L > a) && (0L < b)) { 184 if ((LONG_MIN + b) > a) { 185 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 186 } 187 } 188 } 189 return (a - b); 190} 191 192 193 194long 195dk4ma_long_mul(long a, long b, dk4_er_t *erp) 196{ 197 if ((0L != a) && (0L != b)) { 198 if (LONG_MIN == a) { 199 if (1L != b) { 200 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 201 } 202 } else { 203 if (LONG_MIN == b) { 204 if (1L != a) { 205 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 206 } 207 } else { 208 if (0L < a) { 209 if (0L < b) { 210 if ((LONG_MAX / a) < b) { 211 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 212 } 213 } else { 214 if ((LONG_MIN / a) > b) { 215 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 216 } 217 } 218 } else { 219 if (0L < b) { 220 if ((LONG_MIN / b) > a) { 221 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 222 } 223 } else { 224 if ((LONG_MAX / (0L - a)) < (0L - b)) { 225 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 226 } 227 } 228 } 229 } 230 } 231 } 232 return (a * b); 233} 234 235 236 237long 238dk4ma_long_div(long a, long b, dk4_er_t *erp) 239{ 240 long back = 0; 241 if (0L != b) { 242 if ((LONG_MIN == a) && (-1L == b)) { 243 back = LONG_MAX; 244 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 245 } else { 246 back = a / b; 247 } 248 } else { 249 if (0L < a) { 250 back = LONG_MAX; 251 } else { 252 if (0L > a) { 253 back = LONG_MIN; 254 } 255 } 256 dk4error_set_simple_error_code(erp, DK4_E_MATH_DIVZERO); 257 } 258 return back; 259} 260 261 262 263long 264dk4ma_long_from(dk4_im_t i, dk4_er_t *erp) 265{ 266 if (((dk4_im_t)(LONG_MAX) < i) || ((dk4_im_t)(LONG_MIN) > i)) { 267 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 268 } 269 return ((long)i); 270} 271 272 273 274long 275dk4ma_long_from_double(double d, dk4_er_t *erp) 276{ 277 long back = 0L; 278 if ((double)(LONG_MIN) > d) { 279 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); 280 back = LONG_MIN; 281 } 282 else { 283 if ((double)(LONG_MAX) < d) { 284 dk4error_set_simple_error_code(erp,DK4_E_MATH_OVERFLOW); 285 back = LONG_MAX; 286 } 287 else { 288 back = (long)d; 289 } 290 } 291 return back; 292} 293