It looks like this works, and degrades more gracefully than the other 
methods I've shown when the arguments can't be reduced to Floats:

    def _eval_evalf(self,prec):
        args=[N(x,prec) for x in self.args]
        return N(args[0] % args[1],prec)


On Wednesday, February 27, 2013 6:28:54 PM UTC-8, G B wrote:
>
> > Why not just convert each arg to Float and use %, and leave the details 
> up to Float.__mod__. 
>
> In all honesty, because I have very little idea what I'm doing... =)
>
>
> I just tried this, but it failed:
> def _eval_evalf(self,prec):
>     args=[Float(x,prec) for x in self.args]
>     return N(args[0] % args[1],prec)
>
>
> I put the traceback at the bottom of my message to avoid clutter...
>
>
> >I may not be clear what you're saying, but _eval_evalf only takes two 
> >arguments, self and prec. So where would subs be passed to? 
>
>
> Sorry, I should have been more clear. 
>
>
> As I read the code in EvalfMixin.evalf, it first tries to call 
> evalf(self,prec+4,options). I believe this evalf is in the evalf.py source 
> file itself. This version uses evalf_table for dispatch, rather than 
> relying on self to have its own implementation. One of the fields of 
> 'options' is the subs parameter passed to EvalfMixin.evalf
>
>
> If this version of evalf raises NotImplementedError, then EvalfMixin.evalf 
> tries to call self._eval_evalf(prec). It doesn't try to pass the options 
> parameter to the _eval_evalf implemented in self, and therefore can't carry 
> the subs parameter passed to the EvalfMixin.evalf(self,n,subs,...) call. 
>
>
> I don't know the reason for the different calling conventions. It appears 
> like the dispatch table would best handle classes that can't be extended 
> with _eval_evalf, while leaving each class responsible for it's own 
> implementation otherwise. The options seem equally useful to both 
> implementation routes.  I'm guessing this was an oversight, but I don't 
> know the history.
>
>
> Cheers--
> Greg
>
>
> Here's that traceback:
> -------------------------------------------------------------------
>     100     def _eval_evalf(self,prec):
> --> 101         args=[Float(x,prec) for x in self.args]
>     102         return N(args[0] % args[1],prec)
>     103 #        return N(mpmath.fmod(*[N(x,prec) for x in 
> self.args]),prec)
>
> /Library/Python/2.7/site-packages/sympy/core/numbers.pyc in __new__(cls, 
> num, prec)
>     589                 _mpf_ = mpf_norm(_mpf_, prec)
>     590         else:
> --> 591             _mpf_ = mpmath.mpf(num)._mpf_
>     592 
>     593         if not num:
>
> /Library/Python/2.7/site-packages/sympy/mpmath/ctx_mp_python.pyc in 
> __new__(cls, val, **kwargs)
>      75         else:
>      76             v = new(cls)
> ---> 77             v._mpf_ = mpf_pos(cls.mpf_convert_arg(val, prec, 
> rounding), prec, rounding)
>      78             return v
>      79 
>
> /Library/Python/2.7/site-packages/sympy/mpmath/ctx_mp_python.pyc in 
> mpf_convert_arg(cls, x, prec, rounding)
>      94                 return a
>      95             raise ValueError("can only create mpf from zero-width 
> interval")
> ---> 96         raise TypeError("cannot create mpf from " + repr(x))
>      97 
>      98     @classmethod
>
> TypeError: cannot create mpf from acos(cos(39*pi/115))/(2*pi)
>
>
>
>
>
>
>
> On Wednesday, February 27, 2013 4:55:46 PM UTC-8, Aaron Meurer wrote:
>>
>> On Wed, Feb 27, 2013 at 5:46 PM, G B <[email protected]> wrote: 
>> > I'm not sure it matters in the end, but it looks like 
>> > Mod(Rational(15,7),1).n() works ok too.  I think what's happening is 
>> that 
>> > when pi isn't in the argument list, it basically gets simplified when 
>> the 
>> > class construction calls Mod.eval but Mod.eval doesn't know how to 
>> simplify 
>> > with pi. 
>> > 
>> > I've patched this into my Mod class: 
>> > 
>> >     def _eval_evalf(self,prec): 
>> >         return N(mpmath.fmod(*[N(x,prec) for x in self.args]),prec) 
>>
>> You're passing SymPy Floats to the mpmath function, which is not 
>> really correct (though I guess it works).  Why not just convert each 
>> arg to Float and use %, and leave the details up to Float.__mod__. 
>>
>> > 
>> > It solves my immediate problem, but given how complex the evalf 
>> functions 
>> > are for everything else, I get the feeling I've done something 
>> horribly, 
>> > inexcusably naive here.  Am I missing anything? 
>> > 
>> > I tried Chris' examples and Mod(1e-40,1) returns 0 with my method even 
>> > though mpmath.fmod(1e-40,1) returns 1e-40.  It also returns zero if I 
>> write 
>> > it as Mod(Float(1e-40),S(1)).  I get the proper results with 
>> > Mod(1e-40,1,evaluate=False).n(). 
>> > 
>> > Again, the problem appears to be in Mod.eval, but I'm not sure where. 
>> > 
>> > The other thing I noticed going through EvalfMixin.evalf is that the 
>> options 
>> > parameter isn't passed to self._eval_evalf, which means that subs 
>> parameters 
>> > won't get passed unless _eval_evalf is in the evalf_table.  I don't 
>> know if 
>> > this was intentional or an oversight. 
>>
>> I may not be clear what you're saying, but _eval_evalf only takes two 
>> arguments, self and prec.  So where would subs be passed to? 
>>
>> Aaron Meurer 
>>
>> > 
>> > Cheers-- 
>> >  Greg 
>> > 
>> > 
>> > 
>> > On Wednesday, February 27, 2013 3:40:57 PM UTC-8, Aaron Meurer wrote: 
>> >> 
>> >> On Wed, Feb 27, 2013 at 1:41 PM, Chris Smith <[email protected]> 
>> wrote: 
>> >> >> It looks like Mod doesn't implement evalf at all, and it doesn't 
>> work 
>> >> >> automatically (that only happens if the function name is the same 
>> as 
>> >> >> the mpmath function name).  It should be easy.  Just evaluate the 
>> >> >> arguments, and then take the mod of them. 
>> >> > 
>> >> > In general this is not going to work: 
>> >> > 
>> >> > ``` 
>> >> >>>> Mod(1e-30,3) 
>> >> > 1.00000000000000e-30 
>> >> >>>> Mod(1e-40,3) 
>> >> > 0.0 
>> >> > ``` 
>> >> > 
>> >> > whereas 
>> >> > 
>> >> > ``` 
>> >> >>>> 1e-40 % 3 
>> >> > 9.9999999999999993e-41 
>> >> > ``` 
>> >> 
>> >> Isn't that just a roundoff error. If you use Float, you get 1e-40. 
>> >> 
>> >> Aaron Meurer 
>> >> 
>> >> > 
>> >> > Something like this might work when a > b (when a < b the answer is 
>> >> > `a`): 
>> >> > 
>> >> > ``` 
>> >> >>>> a,b=pi**3,S(3) 
>> >> >>>> (a - round(a/b)*b).n() 
>> >> > 1.00627668029982 
>> >> >>>> a.n() % b.n() 
>> >> > 1.00627668029982 
>> >> > ``` 
>> >> > 
>> >> > -- 
>> >> > You received this message because you are subscribed to the Google 
>> >> > Groups "sympy" group. 
>> >> > To unsubscribe from this group and stop receiving emails from it, 
>> send 
>> >> > an email to [email protected]. 
>> >> > To post to this group, send email to [email protected]. 
>> >> > Visit this group at http://groups.google.com/group/sympy?hl=en. 
>> >> > For more options, visit https://groups.google.com/groups/opt_out. 
>> >> > 
>> >> > 
>> > 
>> > -- 
>> > You received this message because you are subscribed to the Google 
>> Groups 
>> > "sympy" group. 
>> > To unsubscribe from this group and stop receiving emails from it, send 
>> an 
>> > email to [email protected]. 
>> > To post to this group, send email to [email protected]. 
>> > Visit this group at http://groups.google.com/group/sympy?hl=en. 
>> > For more options, visit https://groups.google.com/groups/opt_out. 
>> > 
>> > 
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to