arithmetic.h 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // Copyright © 2019 Ariadne Devos
  3. #ifndef _sHT_LOGIC_ARITHMETIC
  4. #define _sHT_LOGIC_ARITHMETIC
  5. #include <sHT/logic/failbit.h>
  6. /** The variable really is in ℕ (for proofs), but
  7. the range supported by the computer is limited.
  8. The actual value the code sees may wrap-around,
  9. so that must always be checked -- with the following
  10. functions. */
  11. #define sHT_overflowing
  12. /** Calculate a * b + c, tracking overflow
  13. (a, b, c : T, ret : T *, T ⊂ ℕ, M ∈ { uintN_t | N })
  14. Requires:
  15. - good(M, *m) <-> { a, b, c } ⊂ \bounds(T)
  16. - (read ^ write) (*ret)
  17. - (read ^ write ^ set) (*mask)
  18. Invariant:
  19. - failvalue(M, *m)
  20. Ensures:
  21. - good(M, *m) := good(M, old *m) ^ (a * b + c ∈ \bounds(T))
  22. - ret = a * b + c */
  23. #define sHT_muladd_overflow(T, M, ret, a, b, c, m) \
  24. do { \
  25. /* Computation is correct, failure is always maintained,
  26. a, b and c are non-negative so failure is set on overflow. */ \
  27. sHT_fail_if(M, (m), __builtin_mul_overflow((a), (b), (ret))); \
  28. sHT_fail_if(M, (m), __builtin_add_overflow(*(ret), (c), (ret))); \
  29. } while (0)
  30. #endif