@isuruf About

This is interesting. Did you compare the Python timings also?

`sin(p)`

.This is interesting. Did you compare the Python timings also?

Btw, how do you decide how many terms of you need in

`sin(x)`

to get the required order in the final expansion?
@shivamvats, I didn't compare python timings. You need exactly the order terms in

`sin(x)`

It is a simplified version of

`rs_series_from_list`

@isuruf Even in Python, substitution seems to be faster. You might want to look at rs_fun. It also uses

`rs_series_from_list`

. The idea was that since `rs_tan`

uses `rs_fun`

, expanding `rs_sin`

using `rs_tan`

should be fast. But, now I notice that `rs_fun`

doesn't get called by `rs_tan`

for one generator (in which case rs_sin calls rs_tan).
We can actually do with fewer terms. For example:

```
In [45]: rs_sin(x**2,x,10)
Out[45]: -1/6*x**6 + x**2
In [46]: p = rs_sin(x,x,5)
In [47]: rs_subs(p,{x:x**2},x,10)
Out[47]: -1/6*x**6 + x**2
```

So, if we implement

`rs_fun`

and use it in `rs_tan`

, it should make `rs_sin`

faster too.
Comparing

`sin(cos(1+x))`

with Sage/Pynac needs to acknowledge that Pynac arrives at the result by differentiation. The advantage
of differentiation is that any function can be expanded that just has a

`diff()`

member, no additional code needed in `series()`

.
Ah. yes. I'll add another method that uses

`diff`

for generating the series
```
import symengine as se
def series_se(fun, x, p):
t = fun.subs({x:0})
d = fun
fac = se.Integer(1)
for i in range(1, p):
fac *= i
d = d.diff(x)
t += x**i/fac*d.subs({x:0})
return t
x = se.Symbol("x")
%time e=g(se.sin(se.cos(x+1)), x, 30)
```

takes `26.2ms`

whereas Pynac 0.5.3 takes `115ms`

So that's only 5x faster instead of 10x faster. Accordingly using diff is about 2x slower than polys in symengine, right?

Yes

Why did test for #700 failed?

That's a network failure in appveyor VM. I restarted the build

thanks

Hello everyone,

I was working on #698, and the PolyGamma function takes only non-negative integers as it's first argument. http://mathworld.wolfram.com/PolygammaFunction.html So, what if someone calls

`polygamma(n,x)`

and I know for sure that `n`

is not an integer (say `Rational`

), how do I return an invalid response?
I assume

`is_canonical()`

only checks if the expression is in it's simplest form or not, and not if the expression is valid
throw a

`std::runtime_error`

Where should the checking be happening? In

`is_canonical()`

or in `polygamma`

?
Both

It returns

`false`

in `is_canonical()`

(and not the `runtime_error`

) right?
Just confirming

Yes.

Are there functions like

`is_not_a`

implemented? or I have to make cases to check if it's definitely not an `int`

`is_canonical`

checks if it's in simplest form and the expression is valid. If code is written correctly, then output of `is_canonical`

would be true everywhere
`not is_a`

works
No, what I mean is, say I pass an

`Add`

to it. That'll return `true`

on `not is_a`

. But it doesn't mean it won't evaluate to an int. In other words, a function `is_definitely_not`

Ah, there's nothing like that

You can check that if it is a number

`is_a_Number`

then it should be an `Integer`

Oh right! that works

Btw,

`polygamma(n, x)`

is defined if `n`

is not an integer right?
no, it is not

o_O

Will check it out, thanks

Strange, it does not talk about a non integer

`n`

either on Wikipedia or on Mathworld
Anyways, i'll keep it in mind

In wikipedia, there's a integral representation

Ah

```
sage: psi(.1,.1).n()
-10.4237549404111
```

Another question, so if

`n`

is and `int >= 0`

, should `is_canonical()`

return `false`

? As technically it can be broken down into a multiplication of a `factorial`

and a `Zeta`

. Would that be considered a simpler form or not?
The simplification would be done by a polylog member function?

In Sage these are done autmatically but this is just a convention.

Does it have to be a function? I can't just the return the result in

`polygamma(x,n)`

```
RCP<const Basic> zeta(const RCP<const Basic> &s, const RCP<const Basic> &a)
{
if (is_a_Number(*s)) {
if (rcp_static_cast<const Number>(s)->is_zero()) {
if (is_a_Number(*a) and
rcp_static_cast<const Number>(a)->is_negative()) {
return sub(div(minus_one, i2), a);
} else {
return sub(div(one, i2), a);
}
} else if (rcp_static_cast<const Number>(s)->is_one()) {
throw std::runtime_error("Complex infinity is not yet implemented");
} else if (is_a<Integer>(*s) and is_a<Integer>(*a)) {
// Implement Harmonic and simplify this
return make_rcp<const Zeta>(s, a);
}
}
return make_rcp<const Zeta>(s, a);
}
```

Here, `zeta`

returns simplified versions automatically (if possible) (at the same time it's `is_canonical()`

will return `false`

)Should it be the same way in

`PolyGamma`

?
You could because it's always a

`Basic`

but I just see that there is a member function `rewrite_as_zeta`

so you could do it there
One more question, in general, is it true that when

`is_canonical()`

return false, `function()`

won't return the class `Function`

(and vice versa)?
@srajangarg, yes

And what I meant to also ask is, how exactly is "simplest form" defined? If a

`PolyGamma`

can be expressed in terms of some other already defined classes, does it mean it's not in the simplest form? Is this always true? Even if the "simplified" form is actually pretty complicated (in terms of already defined stuff)
It depends on the function. For eg:

`sin(pi/2 -x)`

returns `cos(x)`

because it's simpler. On the other hand `sinh(x)`

doesn't return `(exp(x)-exp(-x))/2`

Alright! Thanks!

@certik Your opinion on #715 ?

Is there any existing function which does modular exponentiation?

powermod

Cool.