def _sollya_annotate(self, center, rad, polys): import sagesollya as sollya logger = logging.getLogger(__name__ + ".sollya") logger.info("calling annotatefunction() on %s derivatives", len(polys)) center = QQ(center) sollya_fun = self._sollya_object # sollya keeps all annotations, let's not bother with selecting # the best one for ord, pol0 in enumerate(polys): pol = ZZ(ord).factorial() * pol0 sollya_pol = sum( [c.center() * sollya.x**k for k, c in enumerate(pol)]) dom = RIF(center - rad, center + rad) # XXX: dangerous when inexact err_pol = pol.map_coefficients(lambda c: c - c.squash()) err = RIF(err_pol(RBF.zero().add_error(rad))) with sollya.settings(display=sollya.dyadic): logger = logging.getLogger(__name__ + ".sollya.annotate") logger.debug("annotatefunction(%s, %s, %s, %s, %s);", sollya_fun, sollya_pol, sollya.SollyaObject(dom), sollya.SollyaObject(err), sollya.SollyaObject(center)) sollya.annotatefunction(sollya_fun, sollya_pol, dom, err, center) sollya_fun = sollya.diff(sollya_fun) logger.info("...done")
def _disk(self, pt): assert pt.is_real() # Since approximation disks satisfy 2·rad ≤ dist(center, sing), any # approximation disk containing pt must have rad ≤ dist(pt, sing) max_rad = pt.dist_to_sing().min(self.max_rad) # What we want is the largest such disk containing pt expo = ZZ(max_rad.log(2).upper().ceil()) - 1 # rad = 2^expo logger.log(logging.DEBUG - 2, "max_rad = %s, expo = %s", max_rad, expo) while True: approx_pt = pt.approx_abs_real(-expo) mantissa = (approx_pt.squash() >> expo).floor() if ZZ(mantissa) % 2 == 0: mantissa += 1 center = mantissa << expo dist = Point(center, pt.dop).dist_to_sing() rad = RBF.one() << expo logger.log( logging.DEBUG - 2, "candidate disk: approx_pt = %s, mantissa = %s, " "center = %s, dist = %s, rad = %s", approx_pt, mantissa, center, dist, rad) if safe_ge(dist >> 1, rad): break expo -= 1 logger.debug("disk for %s: center=%s, rad=%s", pt, center, rad) # pt may be a ball with nonzero radius: check that it is contained in # our candidate disk log = RBF.zero() if 0 in approx_pt else approx_pt.abs().log(2) F = RealBallField(ZZ((expo - log).max(0).upper().ceil()) + 10) dist_to_center = (F(approx_pt) - F(center)).abs() if not safe_le(dist_to_center, rad): assert not safe_gt((approx_pt.squash() - center).squash(), rad) logger.info("check that |%s - %s| < %s failed", approx_pt, center, rad) return None, None # exactify center so that subsequent computations are not limited by the # precision of its parent center = QQ(center) return center, rad