-ex sin_eval(ex const & x)
-{
- // sin(n*Pi) -> 0
- ex xOverPi=x/Pi;
- if (xOverPi.info(info_flags::integer))
- return exZERO();
-
- // sin((2n+1)*Pi/2) -> {+|-}1
- ex xOverPiMinusHalf=xOverPi-exHALF();
- if (xOverPiMinusHalf.info(info_flags::even))
- return exONE();
- else if (xOverPiMinusHalf.info(info_flags::odd))
- return exMINUSONE();
+static ex sin_eval(const ex & x)
+{
+ // sin(n/d*Pi) -> { all known non-nested radicals }
+ ex SixtyExOverPi = _ex60()*x/Pi;
+ ex sign = _ex1();
+ if (SixtyExOverPi.info(info_flags::integer)) {
+ numeric z = mod(ex_to_numeric(SixtyExOverPi),_num120());
+ if (z>=_num60()) {
+ // wrap to interval [0, Pi)
+ z -= _num60();
+ sign = _ex_1();
+ }
+ if (z>_num30()) {
+ // wrap to interval [0, Pi/2)
+ z = _num60()-z;
+ }
+ if (z.is_equal(_num0())) // sin(0) -> 0
+ return _ex0();
+ if (z.is_equal(_num5())) // sin(Pi/12) -> sqrt(6)/4*(1-sqrt(3)/3)
+ return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2()));
+ if (z.is_equal(_num6())) // sin(Pi/10) -> sqrt(5)/4-1/4
+ return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4());
+ if (z.is_equal(_num10())) // sin(Pi/6) -> 1/2
+ return sign*_ex1_2();
+ if (z.is_equal(_num15())) // sin(Pi/4) -> sqrt(2)/2
+ return sign*_ex1_2()*power(_ex2(),_ex1_2());
+ if (z.is_equal(_num18())) // sin(3/10*Pi) -> sqrt(5)/4+1/4
+ return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4());
+ if (z.is_equal(_num20())) // sin(Pi/3) -> sqrt(3)/2
+ return sign*_ex1_2()*power(_ex3(),_ex1_2());
+ if (z.is_equal(_num25())) // sin(5/12*Pi) -> sqrt(6)/4*(1+sqrt(3)/3)
+ return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2()));
+ if (z.is_equal(_num30())) // sin(Pi/2) -> 1
+ return sign*_ex1();
+ }