ntheory_funcs.cpp
1 #include <symengine/ntheory.h>
2 #include <symengine/ntheory_funcs.h>
3 #include <symengine/prime_sieve.h>
4 
5 namespace SymEngine
6 {
7 
8 PrimePi::PrimePi(const RCP<const Basic> &arg) : OneArgFunction(arg)
9 {
10  SYMENGINE_ASSIGN_TYPEID()
11  SYMENGINE_ASSERT(is_canonical(arg))
12 }
13 
14 bool PrimePi::is_canonical(const RCP<const Basic> &arg) const
15 {
16  if (is_a_Number(*arg) or is_a<Constant>(*arg)) {
17  return false;
18  } else {
19  return true;
20  }
21 }
22 
23 RCP<const Basic> PrimePi::create(const RCP<const Basic> &arg) const
24 {
25  return primepi(arg);
26 }
27 
28 RCP<const Basic> primepi(const RCP<const Basic> &arg)
29 {
30  if (is_a_Number(*arg)) {
31  if (is_a<NaN>(*arg)) {
32  return arg;
33  } else if (is_a<Infty>(*arg)) {
34  if (down_cast<const Infty &>(*arg).is_negative_infinity()) {
35  return make_rcp<const Integer>(integer_class(0));
36  } else {
37  return arg;
38  }
39  } else if (down_cast<const Number &>(*arg).is_complex()) {
40  throw SymEngineException("Complex can't be passed to primepi!");
41  } else if (down_cast<const Number &>(*arg).is_negative()) {
42  return make_rcp<const Integer>(integer_class(0));
43  }
44  }
45  if (is_a_Number(*arg) or is_a<Constant>(*arg)) {
46  unsigned int num
47  = (unsigned int)down_cast<const Integer &>(*SymEngine::floor(arg))
48  .as_uint();
49  Sieve::iterator pi(num);
50  unsigned long int p = 0;
51  while ((pi.next_prime()) <= num) {
52  p++;
53  }
54  return make_rcp<const Integer>(integer_class(p));
55  }
56  return make_rcp<const PrimePi>(arg);
57 }
58 
59 Primorial::Primorial(const RCP<const Basic> &arg) : OneArgFunction(arg)
60 {
61  SYMENGINE_ASSIGN_TYPEID()
62  SYMENGINE_ASSERT(is_canonical(arg))
63 }
64 
65 bool Primorial::is_canonical(const RCP<const Basic> &arg) const
66 {
67  if (is_a_Number(*arg) or is_a<Constant>(*arg)) {
68  return false;
69  } else {
70  return true;
71  }
72 }
73 
74 RCP<const Basic> Primorial::create(const RCP<const Basic> &arg) const
75 {
76  return primorial(arg);
77 }
78 
79 RCP<const Basic> primorial(const RCP<const Basic> &arg)
80 {
81  if (is_a_Number(*arg)) {
82  if (is_a<NaN>(*arg)) {
83  return arg;
84  }
85  if (down_cast<const Number &>(*arg).is_positive()) {
86  if (is_a<Infty>(*arg)) {
87  return arg;
88  }
89  } else {
90  throw SymEngineException(
91  "Only positive numbers are allowed for primorial!");
92  }
93  }
94  if (is_a_Number(*arg) or is_a<Constant>(*arg)) {
95  unsigned long n
96  = down_cast<const Integer &>(*SymEngine::floor(arg)).as_uint();
97  return make_rcp<const Integer>(mp_primorial(n));
98  }
99  return make_rcp<const Primorial>(arg);
100 }
101 
102 } // namespace SymEngine
Basic()
Constructor.
Definition: basic.h:118
RCP< const Basic > create(const RCP< const Basic > &arg) const
Method to construct classes with canonicalization.
Main namespace for SymEngine package.
Definition: add.cpp:19
bool is_a_Number(const Basic &b)
Definition: number.h:130
RCP< const Basic > floor(const RCP< const Basic > &arg)
Canonicalize Floor:
Definition: functions.cpp:568