]>
git.proxmox.com Git - mirror_ovs.git/blob - lib/sat-math.h
2 * Copyright (c) 2008, 2012, 2019 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "openvswitch/util.h"
24 #define __has_builtin(x) 0
27 /* Returns x + y, clamping out-of-range results into the range of the return
29 static inline unsigned int
30 sat_add(unsigned int x
, unsigned int y
)
32 return x
+ y
>= x
? x
+ y
: UINT_MAX
;
34 static inline long long int
35 llsat_add__(long long int x
, long long int y
)
37 return (x
>= 0 && y
>= 0 && x
> LLONG_MAX
- y
? LLONG_MAX
38 : x
< 0 && y
< 0 && x
< LLONG_MIN
- y
? LLONG_MIN
41 static inline long long int
42 llsat_add(long long int x
, long long int y
)
44 #if (__GNUC__ >= 5 || __has_builtin(__builtin_saddll_overflow)) && !__CHECKER__
46 return (!__builtin_saddll_overflow(x
, y
, &sum
) ? sum
47 : x
> 0 ? LLONG_MAX
: LLONG_MIN
);
49 return llsat_add__(x
, y
);
53 /* Returns x - y, clamping out-of-range results into the range of the return
55 static inline unsigned int
56 sat_sub(unsigned int x
, unsigned int y
)
58 return x
>= y
? x
- y
: 0;
60 static inline long long int
61 llsat_sub__(long long int x
, long long int y
)
63 return (x
>= 0 && y
< 0 && x
> LLONG_MAX
+ y
? LLONG_MAX
64 : x
< 0 && y
>= 0 && x
< LLONG_MIN
+ y
? LLONG_MIN
67 static inline long long int
68 llsat_sub(long long int x
, long long int y
)
70 #if (__GNUC__ >= 5 || __has_builtin(__builtin_ssubll_overflow)) && !__CHECKER__
71 long long int difference
;
72 return (!__builtin_ssubll_overflow(x
, y
, &difference
) ? difference
73 : x
>= 0 ? LLONG_MAX
: LLONG_MIN
);
75 return llsat_sub__(x
, y
);
79 /* Returns x * y, clamping out-of-range results into the range of the return
81 static inline unsigned int
82 sat_mul(unsigned int x
, unsigned int y
)
84 return OVS_SAT_MUL(x
, y
);
86 static inline long long int
87 llsat_mul__(long long int x
, long long int y
)
89 return ( x
> 0 && y
> 0 && x
> LLONG_MAX
/ y
? LLONG_MAX
90 : x
< 0 && y
> 0 && x
< LLONG_MIN
/ y
? LLONG_MIN
91 : x
> 0 && y
< 0 && y
< LLONG_MIN
/ x
? LLONG_MIN
92 /* Special case because -LLONG_MIN / -1 overflows: */
93 : x
== LLONG_MIN
&& y
== -1 ? LLONG_MAX
94 : x
< 0 && y
< 0 && x
< LLONG_MAX
/ y
? LLONG_MAX
97 static inline long long int
98 llsat_mul(long long int x
, long long int y
)
100 #if (__GNUC__ >= 5 || __has_builtin(__builtin_smulll_overflow)) && !__CHECKER__
101 long long int product
;
102 return (!__builtin_smulll_overflow(x
, y
, &product
) ? product
103 : (x
> 0) == (y
> 0) ? LLONG_MAX
: LLONG_MIN
);
105 return llsat_mul__(x
, y
);
109 #endif /* sat-math.h */