> 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] <javascript:>>
> 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] <javascript:>.
> > To post to this group, send email to [email protected]<javascript:>.
>
> > 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.