reciprocal_div.h 993 B

123456789101112131415161718192021222324252627282930313233343536
  1. #ifndef _LINUX_RECIPROCAL_DIV_H
  2. #define _LINUX_RECIPROCAL_DIV_H
  3. #include <linux/types.h>
  4. /*
  5. * This algorithm is based on the paper "Division by Invariant
  6. * Integers Using Multiplication" by Torbjörn Granlund and Peter
  7. * L. Montgomery.
  8. *
  9. * The assembler implementation from Agner Fog, which this code is
  10. * based on, can be found here:
  11. * http://www.agner.org/optimize/asmlib.zip
  12. *
  13. * This optimization for A/B is helpful if the divisor B is mostly
  14. * runtime invariant. The reciprocal of B is calculated in the
  15. * slow-path with reciprocal_value(). The fast-path can then just use
  16. * a much faster multiplication operation with a variable dividend A
  17. * to calculate the division A/B.
  18. */
  19. struct reciprocal_value {
  20. u32 m;
  21. u8 sh1, sh2;
  22. };
  23. struct reciprocal_value reciprocal_value(u32 d);
  24. static inline u32 reciprocal_divide(u32 a, struct reciprocal_value R)
  25. {
  26. u32 t = (u32)(((u64)a * R.m) >> 32);
  27. return (t + ((a - t) >> R.sh1)) >> R.sh2;
  28. }
  29. #endif /* _LINUX_RECIPROCAL_DIV_H */