gv_math.h 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /// \file
  2. /// \brief Arithmetic helper functions
  3. /// \ingroup cgraph_utils
  4. #pragma once
  5. #include <assert.h>
  6. #include <limits.h>
  7. #include <stdbool.h>
  8. #include <string.h>
  9. /// comparator for doubles
  10. static inline int fcmp(double a, double b) {
  11. if (a < b) {
  12. return -1;
  13. }
  14. if (a > b) {
  15. return 1;
  16. }
  17. return 0;
  18. }
  19. /// maximum of two integers
  20. static inline int imax(int a, int b) { return a > b ? a : b; }
  21. /// minimum of two integers
  22. static inline int imin(int a, int b) { return a < b ? a : b; }
  23. /**
  24. * \brief are two values precisely the same?
  25. *
  26. * This function should only be used when you know you want comparison with no
  27. * tolerance, which is rare. Floating-point arithmetic accumulates imprecision,
  28. * so equality comparisons should generally include a non-zero tolerance to
  29. * account for this. In general, this function is only applicable for checking
  30. * things like “is this variable unchanged since a previous assignment from a
  31. * literal?”
  32. *
  33. * \param a First operand to comparison
  34. * \param b Second operand to comparison
  35. * \return True if the values are equal
  36. */
  37. static inline bool is_exactly_equal(double a, double b) {
  38. return memcmp(&a, &b, sizeof(a)) == 0;
  39. }
  40. /**
  41. * \brief is a value precisely 0.0?
  42. *
  43. * This function should only be used when you know you want comparison with no
  44. * tolerance, which is rare. Floating-point arithmetic accumulates imprecision,
  45. * so equality comparisons should generally include a non-zero tolerance to
  46. * account for this. Valid `double` representations even include -0.0, for which
  47. * this function will return false. In general, this function is only applicable
  48. * for checking things like “is this variable unchanged since a previous
  49. * assignment from the literal `0`?” or “did this value we parsed from user
  50. * input originate from the string "0.0"?”
  51. *
  52. * \param v Value to check
  53. * \return True if the value is equal to exactly 0.0
  54. */
  55. static inline bool is_exactly_zero(double v) { return is_exactly_equal(v, 0); }
  56. /**
  57. * \brief scale up or down a non-negative integer, clamping to \p [0, INT_MAX]
  58. *
  59. * \param original Value to scale
  60. * \param scale Scale factor to apply
  61. * \return Clamped result
  62. */
  63. static inline int scale_clamp(int original, double scale) {
  64. assert(original >= 0);
  65. if (scale < 0) {
  66. return 0;
  67. }
  68. if (scale > 1 && original > INT_MAX / scale) {
  69. return INT_MAX;
  70. }
  71. return (int)(original * scale);
  72. }