factors.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #ifndef FACTORS_HPP
  2. #define FACTORS_HPP
  3. #include <array>
  4. #include <numeric>
  5. #include <algorithm>
  6. #include <type_traits>
  7. #include "simple/support/algorithm.hpp"
  8. constexpr auto some_primes = std::array
  9. {
  10. 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
  11. 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
  12. 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
  13. 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
  14. 257, 263, 269, 271
  15. };
  16. // what is integer exp that you don't have it, eh? c++, eh? -_-
  17. // TODO: add integer exp to simple::support i guess
  18. template <typename Int, typename Power = Int>
  19. constexpr auto pow(const Int& i, Power p)
  20. -> decltype((Int{}, ++i, i*=i, p-->0, i))
  21. {
  22. auto r = Int{}; ++r; // ugh
  23. while(p-->0) r *= i;
  24. return r;
  25. }
  26. template <typename Prime, typename Power = Prime>
  27. struct prime_factorization
  28. {
  29. std::vector<Prime> primes;
  30. std::vector<Power> powers;
  31. };
  32. template <typename Int, typename Power = Int>
  33. prime_factorization<Int, Power> partial_prime_factorize(Int number)
  34. {
  35. prime_factorization<Int,Power> result{};
  36. for(auto&& prime : some_primes)
  37. {
  38. if(number % prime == 0)
  39. {
  40. result.primes.push_back(prime);
  41. result.powers.push_back(Power{});
  42. do
  43. {
  44. number /= prime;
  45. ++result.powers.back();
  46. }
  47. while(number % prime == 0);
  48. }
  49. if(number == 1)
  50. {
  51. return result;
  52. }
  53. }
  54. result.primes.push_back(number);
  55. result.powers.push_back(Power());
  56. ++result.powers.back();
  57. return result;
  58. }
  59. template <typename PrimeFactors, typename FactorPowers, typename Counter, typename F>
  60. constexpr void for_all_factors(const PrimeFactors& primes, const FactorPowers& powers, Counter&& counter, F&& f)
  61. {
  62. using simple::support::advance_vector;
  63. using std::begin, std::end;
  64. using prime_type = std::remove_cvref_t<decltype(*begin(primes))>;
  65. using power_type = std::remove_cvref_t<decltype(*begin(powers))>;
  66. auto carry = begin(counter);
  67. while(carry != end(counter))
  68. {
  69. std::invoke(std::forward<F>(f),
  70. std::inner_product(
  71. begin(primes), end(primes),
  72. begin(counter), prime_type{} + 1, // ugh
  73. std::multiplies{},
  74. pow<prime_type, power_type>
  75. )
  76. );
  77. carry = advance_vector(counter, powers);
  78. }
  79. }
  80. template <typename PrimeFactors, typename FactorPowers, typename Counter, typename OutItr>
  81. constexpr void all_factors(const PrimeFactors& primes, const FactorPowers& powers, Counter&& counter, OutItr out)
  82. {
  83. for_all_factors(primes, powers, std::forward<Counter>(counter),
  84. [&out](auto factor) { *out++ = factor; }
  85. );
  86. }
  87. #endif /* end of include guard */