| 1 | r""" |
|---|
| 2 | Continued Fractions |
|---|
| 3 | |
|---|
| 4 | \sage implements the field code{ContinuedFractionField} (or \code{CFF} |
|---|
| 5 | for short) of finite simple continued fractions. This is really |
|---|
| 6 | isomorphic to the field $\QQ$ of rational numbers, but with different |
|---|
| 7 | printing and semantics. It should be possible to use this field in |
|---|
| 8 | most cases where one could use $\QQ$, except arithmetic is slower. |
|---|
| 9 | |
|---|
| 10 | The \code{continued\_fraction(x)} command returns an element of |
|---|
| 11 | \code{CFF} that defines a continued fraction expansion to $x$. The |
|---|
| 12 | command \code{continued\_fraction(x,bits)} computes the continued |
|---|
| 13 | fraction expansion of an approximation to $x$ with given bits of |
|---|
| 14 | precision. Use \code{show(c)} to see a continued fraction nicely |
|---|
| 15 | typeset, and \code{latex(c)} to obtain the typeset version, e.g., for |
|---|
| 16 | inclusion in a paper. |
|---|
| 17 | |
|---|
| 18 | EXAMPLES: |
|---|
| 19 | We create some example elements of the continued fraction field. |
|---|
| 20 | |
|---|
| 21 | sage: c = continued_fraction([1,2]); c |
|---|
| 22 | [1, 2] |
|---|
| 23 | sage: c = continued_fraction([3,7,15,1,292]); c |
|---|
| 24 | [3, 7, 15, 1, 292] |
|---|
| 25 | sage: c = continued_fraction(pi); c |
|---|
| 26 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 27 | sage: c.value() |
|---|
| 28 | 245850922/78256779 |
|---|
| 29 | sage: QQ(c) |
|---|
| 30 | 245850922/78256779 |
|---|
| 31 | sage: RealField(200)(QQ(c) - pi) |
|---|
| 32 | -7.8179366199075435400152113059910891481153981448107195930950e-17 |
|---|
| 33 | |
|---|
| 34 | We can also create matrices, polynomials, vectors, etc., over the continued |
|---|
| 35 | fraction field. |
|---|
| 36 | sage: a = random_matrix(CFF, 4) |
|---|
| 37 | sage: a |
|---|
| 38 | [[0, 2] [1] [1] [0, 2]] |
|---|
| 39 | [ [-1] [1] [-1] [-2]] |
|---|
| 40 | [ [2] [1] [-1] [1]] |
|---|
| 41 | [ [-1] [1] [-2] [0, 2]] |
|---|
| 42 | sage: f = a.charpoly() |
|---|
| 43 | sage: f |
|---|
| 44 | [1]*x^4 + ([-1])*x^3 + [3, 1, 3]*x^2 + [3]*x + [-18] |
|---|
| 45 | sage: f(a) |
|---|
| 46 | [[0] [0] [0] [0]] |
|---|
| 47 | [[0] [0] [0] [0]] |
|---|
| 48 | [[0] [0] [0] [0]] |
|---|
| 49 | [[0] [0] [0] [0]] |
|---|
| 50 | sage: vector(CFF, [1/2, 2/3, 3/4, 4/5]) |
|---|
| 51 | ([0, 2], [0, 1, 2], [0, 1, 3], [0, 1, 4]) |
|---|
| 52 | |
|---|
| 53 | """ |
|---|
| 54 | from sage.structure.element import FieldElement |
|---|
| 55 | from sage.structure.parent_gens import ParentWithGens |
|---|
| 56 | from sage.libs.pari.all import pari |
|---|
| 57 | |
|---|
| 58 | from field import Field |
|---|
| 59 | from rational_field import QQ |
|---|
| 60 | from integer_ring import ZZ |
|---|
| 61 | from infinity import infinity |
|---|
| 62 | from real_mpfr import is_RealNumber, RealField |
|---|
| 63 | from real_double import RDF |
|---|
| 64 | from arith import (continued_fraction_list, |
|---|
| 65 | convergent, convergents) |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | class ContinuedFractionField_class(Field): |
|---|
| 69 | """ |
|---|
| 70 | The field of all finite continued fraction of real numbers. |
|---|
| 71 | |
|---|
| 72 | EXAMPLES: |
|---|
| 73 | sage: CFF |
|---|
| 74 | Field of all continued fractions |
|---|
| 75 | sage: ContinuedFractionField() |
|---|
| 76 | Field of all continued fractions |
|---|
| 77 | """ |
|---|
| 78 | def __init__(self): |
|---|
| 79 | ParentWithGens.__init__(self, self) |
|---|
| 80 | self._assign_names(('x'),normalize=False) |
|---|
| 81 | |
|---|
| 82 | def __cmp__(self, right): |
|---|
| 83 | """ |
|---|
| 84 | EXAMPLES: |
|---|
| 85 | sage: CFF == ContinuedFractionField() |
|---|
| 86 | True |
|---|
| 87 | sage: CFF == CDF |
|---|
| 88 | False |
|---|
| 89 | sage: loads(dumps(CFF)) == CFF |
|---|
| 90 | True |
|---|
| 91 | """ |
|---|
| 92 | return cmp(type(self), type(right)) |
|---|
| 93 | |
|---|
| 94 | def __iter__(self): |
|---|
| 95 | """ |
|---|
| 96 | EXAMPLES: |
|---|
| 97 | sage: i = 0 |
|---|
| 98 | sage: for a in CFF: |
|---|
| 99 | ... print a |
|---|
| 100 | ... i += 1 |
|---|
| 101 | ... if i > 5: break |
|---|
| 102 | ... |
|---|
| 103 | [0] |
|---|
| 104 | [1] |
|---|
| 105 | [-1] |
|---|
| 106 | [0, 2] |
|---|
| 107 | [-1, 2] |
|---|
| 108 | [2] |
|---|
| 109 | """ |
|---|
| 110 | for n in QQ: |
|---|
| 111 | yield self(n) |
|---|
| 112 | |
|---|
| 113 | |
|---|
| 114 | def _latex_(self): |
|---|
| 115 | r""" |
|---|
| 116 | EXAMPLES: |
|---|
| 117 | sage: latex(CFF) |
|---|
| 118 | \Bold{CFF} |
|---|
| 119 | """ |
|---|
| 120 | return "\\Bold{CFF}" |
|---|
| 121 | |
|---|
| 122 | def _is_valid_homomorphism_(self, codomain, im_gens): |
|---|
| 123 | try: |
|---|
| 124 | return im_gens[0] == codomain._coerce_(self(1)) |
|---|
| 125 | except TypeError: |
|---|
| 126 | return False |
|---|
| 127 | |
|---|
| 128 | def _repr_(self): |
|---|
| 129 | """ |
|---|
| 130 | EXAMPLES: |
|---|
| 131 | sage: CFF |
|---|
| 132 | Field of all continued fractions |
|---|
| 133 | """ |
|---|
| 134 | return "Field of all continued fractions" |
|---|
| 135 | |
|---|
| 136 | def _coerce_impl(self, x): |
|---|
| 137 | """ |
|---|
| 138 | Anything that implicitly coerces to the rationals or a real |
|---|
| 139 | field, implicitly coerces to the continued fraction field. |
|---|
| 140 | |
|---|
| 141 | EXAMPLES: |
|---|
| 142 | The additions below call _coerce_impl implicitly: |
|---|
| 143 | sage: a = CFF(3/5); a |
|---|
| 144 | [0, 1, 1, 2] |
|---|
| 145 | sage: a + 2/5 |
|---|
| 146 | [1] |
|---|
| 147 | sage: 2/5 + a |
|---|
| 148 | [1] |
|---|
| 149 | sage: 1.5 + a |
|---|
| 150 | [2, 10] |
|---|
| 151 | sage: a + 1.5 |
|---|
| 152 | [2, 10] |
|---|
| 153 | """ |
|---|
| 154 | if is_RealNumber(x): |
|---|
| 155 | return self(x) |
|---|
| 156 | return self._coerce_try(x, [QQ, RDF]) |
|---|
| 157 | |
|---|
| 158 | def __call__(self, x, bits=None): |
|---|
| 159 | """ |
|---|
| 160 | INPUT: |
|---|
| 161 | x -- a number |
|---|
| 162 | bits -- integer (optional) the number of bits of the |
|---|
| 163 | input number to use when computing the continued fraction. |
|---|
| 164 | |
|---|
| 165 | EXAMPLES: |
|---|
| 166 | sage: CFF(1.5) |
|---|
| 167 | [1, 2] |
|---|
| 168 | sage: CFF(e) |
|---|
| 169 | [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, 11] |
|---|
| 170 | sage: CFF(pi) |
|---|
| 171 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 172 | sage: CFF([1,2,3]) |
|---|
| 173 | [1, 2, 3] |
|---|
| 174 | sage: CFF(15/17) |
|---|
| 175 | [0, 1, 7, 2] |
|---|
| 176 | sage: c2 = loads(dumps(CFF)) |
|---|
| 177 | sage: c2(CFF(15/17)).parent() is c2 |
|---|
| 178 | True |
|---|
| 179 | |
|---|
| 180 | We illustrate varying the bits parameter: |
|---|
| 181 | sage: CFF(pi) |
|---|
| 182 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 183 | sage: CFF(pi, bits=5) |
|---|
| 184 | [3, 8] |
|---|
| 185 | sage: CFF(pi, bits=80) |
|---|
| 186 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1, 84, 1] |
|---|
| 187 | sage: CFF(pi, bits=100) |
|---|
| 188 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1, 84, 2, 1, 1, 15, 3, 14] |
|---|
| 189 | """ |
|---|
| 190 | if not bits is None: |
|---|
| 191 | x = RealField(bits)(x) |
|---|
| 192 | return ContinuedFraction(self, x) |
|---|
| 193 | |
|---|
| 194 | def __len__(self): |
|---|
| 195 | """ |
|---|
| 196 | EXAMPLES: |
|---|
| 197 | sage: len(CFF) |
|---|
| 198 | Traceback (most recent call last): |
|---|
| 199 | ... |
|---|
| 200 | TypeError: len() of unsized object |
|---|
| 201 | """ |
|---|
| 202 | raise TypeError, 'len() of unsized object' |
|---|
| 203 | |
|---|
| 204 | def gens(self): |
|---|
| 205 | """ |
|---|
| 206 | EXAMPLES: |
|---|
| 207 | sage: CFF.gens() |
|---|
| 208 | ([1],) |
|---|
| 209 | """ |
|---|
| 210 | return (self(1), ) |
|---|
| 211 | |
|---|
| 212 | def gen(self, n=0): |
|---|
| 213 | """ |
|---|
| 214 | EXAMPLES: |
|---|
| 215 | sage: CFF.gen() |
|---|
| 216 | [1] |
|---|
| 217 | sage: CFF.0 |
|---|
| 218 | [1] |
|---|
| 219 | """ |
|---|
| 220 | |
|---|
| 221 | if n == 0: |
|---|
| 222 | return self(1) |
|---|
| 223 | else: |
|---|
| 224 | raise IndexError, "n must be 0" |
|---|
| 225 | |
|---|
| 226 | def degree(self): |
|---|
| 227 | """ |
|---|
| 228 | EXAMPLES: |
|---|
| 229 | sage: CFF.degree() |
|---|
| 230 | 1 |
|---|
| 231 | """ |
|---|
| 232 | return 1 |
|---|
| 233 | |
|---|
| 234 | def ngens(self): |
|---|
| 235 | """ |
|---|
| 236 | EXAMPLES: |
|---|
| 237 | sage: CFF.ngens() |
|---|
| 238 | 1 |
|---|
| 239 | """ |
|---|
| 240 | return 1 |
|---|
| 241 | |
|---|
| 242 | def is_field(self): |
|---|
| 243 | """ |
|---|
| 244 | Return True, since the continued fraction field is a field. |
|---|
| 245 | |
|---|
| 246 | EXAMPLES: |
|---|
| 247 | sage: CFF.is_field() |
|---|
| 248 | True |
|---|
| 249 | """ |
|---|
| 250 | return True |
|---|
| 251 | |
|---|
| 252 | def is_finite(self): |
|---|
| 253 | """ |
|---|
| 254 | Return False, since the continued fraction field is not finite. |
|---|
| 255 | |
|---|
| 256 | EXAMPLES: |
|---|
| 257 | sage: CFF.is_finite() |
|---|
| 258 | False |
|---|
| 259 | """ |
|---|
| 260 | return False |
|---|
| 261 | |
|---|
| 262 | def is_atomic_repr(self): |
|---|
| 263 | """ |
|---|
| 264 | Return False, since continued fractions are not atomic. |
|---|
| 265 | |
|---|
| 266 | EXAMPLES: |
|---|
| 267 | sage: CFF.is_atomic_repr() |
|---|
| 268 | False |
|---|
| 269 | """ |
|---|
| 270 | return False |
|---|
| 271 | |
|---|
| 272 | def characteristic(self): |
|---|
| 273 | """ |
|---|
| 274 | Return 0, since the continued fraction field has characteristic 0. |
|---|
| 275 | |
|---|
| 276 | EXAMPLES: |
|---|
| 277 | sage: c = CFF.characteristic(); c |
|---|
| 278 | 0 |
|---|
| 279 | sage: parent(c) |
|---|
| 280 | Integer Ring |
|---|
| 281 | """ |
|---|
| 282 | return ZZ(0) |
|---|
| 283 | |
|---|
| 284 | def order(self): |
|---|
| 285 | """ |
|---|
| 286 | EXAMPLES: |
|---|
| 287 | sage: CFF.order() |
|---|
| 288 | +Infinity |
|---|
| 289 | """ |
|---|
| 290 | return infinity |
|---|
| 291 | |
|---|
| 292 | def random_element(self, num_bound=2, den_bound=2): |
|---|
| 293 | """ |
|---|
| 294 | EXAMPLES: |
|---|
| 295 | sage: CFF.random_element(10,10) |
|---|
| 296 | [0, 4] |
|---|
| 297 | """ |
|---|
| 298 | return self(QQ.random_element(num_bound = num_bound, den_bound = den_bound)) |
|---|
| 299 | |
|---|
| 300 | |
|---|
| 301 | class ContinuedFraction(FieldElement): |
|---|
| 302 | def __init__(self, parent, x): |
|---|
| 303 | FieldElement.__init__(self, parent) |
|---|
| 304 | if isinstance(x, ContinuedFraction): |
|---|
| 305 | self._x = list(x._x) |
|---|
| 306 | elif isinstance(x, (list, tuple)): |
|---|
| 307 | x = [ZZ(a) for a in x] |
|---|
| 308 | for i in range(1,len(x)): |
|---|
| 309 | if x[i] <= 0: |
|---|
| 310 | raise ValueError, "each entry except the first must be positive" |
|---|
| 311 | self._x = list(x) |
|---|
| 312 | else: |
|---|
| 313 | self._x = [ZZ(a) for a in continued_fraction_list(x)] |
|---|
| 314 | |
|---|
| 315 | def __getitem__(self, n): |
|---|
| 316 | """ |
|---|
| 317 | Returns n-th term of the continued fraction. |
|---|
| 318 | |
|---|
| 319 | OUTPUT: |
|---|
| 320 | an integer |
|---|
| 321 | |
|---|
| 322 | EXAMPLES: |
|---|
| 323 | sage: a = continued_fraction(pi); a |
|---|
| 324 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 325 | sage: a[4] |
|---|
| 326 | 292 |
|---|
| 327 | sage: a[-2] |
|---|
| 328 | 14 |
|---|
| 329 | """ |
|---|
| 330 | return self._x[n] |
|---|
| 331 | |
|---|
| 332 | def __getslice__(self, i, j): |
|---|
| 333 | """ |
|---|
| 334 | OUTPUT: |
|---|
| 335 | a continued fraction |
|---|
| 336 | |
|---|
| 337 | EXAMPLES: |
|---|
| 338 | sage: a = continued_fraction(pi); a |
|---|
| 339 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 340 | sage: a[2:5] |
|---|
| 341 | [15, 1, 292] |
|---|
| 342 | sage: a[:3] |
|---|
| 343 | [3, 7, 15] |
|---|
| 344 | sage: a[4:] |
|---|
| 345 | [292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 346 | """ |
|---|
| 347 | return ContinuedFraction(self.parent(), self._x[i:j]) |
|---|
| 348 | |
|---|
| 349 | def _repr_(self): |
|---|
| 350 | """ |
|---|
| 351 | EXAMPLES: |
|---|
| 352 | sage: a = continued_fraction(pi); a |
|---|
| 353 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 354 | sage: a.rename('continued fraction of pi') |
|---|
| 355 | sage: a |
|---|
| 356 | continued fraction of pi |
|---|
| 357 | """ |
|---|
| 358 | return str(self._x) |
|---|
| 359 | |
|---|
| 360 | def convergents(self): |
|---|
| 361 | """ |
|---|
| 362 | Return a list of rational numbers, which are the partial |
|---|
| 363 | convergents of this continued fraction. |
|---|
| 364 | |
|---|
| 365 | OUTPUT: |
|---|
| 366 | list of rational numbers |
|---|
| 367 | |
|---|
| 368 | EXAMPLES: |
|---|
| 369 | sage: a = CFF(pi, bits=33); a |
|---|
| 370 | [3, 7, 15, 1, 292, 2] |
|---|
| 371 | sage: a.convergents() |
|---|
| 372 | [3, 22/7, 333/106, 355/113, 103993/33102, 208341/66317] |
|---|
| 373 | sage: a.value() |
|---|
| 374 | 208341/66317 |
|---|
| 375 | sage: a[:-1].value() |
|---|
| 376 | 103993/33102 |
|---|
| 377 | """ |
|---|
| 378 | return convergents(self._x) |
|---|
| 379 | |
|---|
| 380 | def convergent(self, n): |
|---|
| 381 | """ |
|---|
| 382 | Return the n-th partial convergent to self. |
|---|
| 383 | |
|---|
| 384 | OUTPUT: |
|---|
| 385 | rational number |
|---|
| 386 | |
|---|
| 387 | EXAMPLES: |
|---|
| 388 | sage: a = CFF(pi, bits=33); a |
|---|
| 389 | [3, 7, 15, 1, 292, 2] |
|---|
| 390 | sage: a.convergents() |
|---|
| 391 | [3, 22/7, 333/106, 355/113, 103993/33102, 208341/66317] |
|---|
| 392 | sage: a.convergent(0) |
|---|
| 393 | 3 |
|---|
| 394 | sage: a.convergent(1) |
|---|
| 395 | 22/7 |
|---|
| 396 | sage: a.convergent(4) |
|---|
| 397 | 103993/33102 |
|---|
| 398 | """ |
|---|
| 399 | return convergent(self._x, n) |
|---|
| 400 | |
|---|
| 401 | def __len__(self): |
|---|
| 402 | """ |
|---|
| 403 | Return the number of terms in this continued fraction. |
|---|
| 404 | |
|---|
| 405 | EXAMPLES: |
|---|
| 406 | sage: len(continued_fraction([1,2,3,4,5]) ) |
|---|
| 407 | 5 |
|---|
| 408 | """ |
|---|
| 409 | return len(self._x) |
|---|
| 410 | |
|---|
| 411 | def pn(self, n): |
|---|
| 412 | """ |
|---|
| 413 | Return the number of the n-th partial convergent, computed |
|---|
| 414 | using the recurrence. |
|---|
| 415 | |
|---|
| 416 | EXAMPLES: |
|---|
| 417 | sage: c = continued_fraction(pi); c |
|---|
| 418 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 419 | sage: c.pn(0), c.qn(0) |
|---|
| 420 | (3, 1) |
|---|
| 421 | sage: len(c) |
|---|
| 422 | 14 |
|---|
| 423 | sage: c.pn(13), c.qn(13) |
|---|
| 424 | (245850922, 78256779) |
|---|
| 425 | """ |
|---|
| 426 | n = ZZ(n) |
|---|
| 427 | if n < -2: |
|---|
| 428 | raise ValueError, "n must be at least -2" |
|---|
| 429 | if n > len(self._x): |
|---|
| 430 | raise ValueError, "n must be at most %s"%len(self._x) |
|---|
| 431 | try: |
|---|
| 432 | return self.__pn[n+2] |
|---|
| 433 | except AttributeError: |
|---|
| 434 | self.__pn = [0, 1, self._x[0]] |
|---|
| 435 | except IndexError: |
|---|
| 436 | pass |
|---|
| 437 | for k in range(len(self.__pn), n+3): |
|---|
| 438 | self.__pn.append(self._x[k-2]*self.__pn[k-1] + self.__pn[k-2]) |
|---|
| 439 | return self.__pn[n+2] |
|---|
| 440 | |
|---|
| 441 | def qn(self, n): |
|---|
| 442 | """ |
|---|
| 443 | Return the denominator of the n-th partial convergent, computed |
|---|
| 444 | using the recurrence. |
|---|
| 445 | |
|---|
| 446 | EXAMPLES: |
|---|
| 447 | sage: c = continued_fraction(pi); c |
|---|
| 448 | [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3] |
|---|
| 449 | sage: c.pn(0), c.qn(0) |
|---|
| 450 | (3, 1) |
|---|
| 451 | sage: len(c) |
|---|
| 452 | 14 |
|---|
| 453 | sage: c.pn(13), c.qn(13) |
|---|
| 454 | (245850922, 78256779) |
|---|
| 455 | """ |
|---|
| 456 | n = ZZ(n) |
|---|
| 457 | n = ZZ(n) |
|---|
| 458 | if n < -2: |
|---|
| 459 | raise ValueError, "n must be at least -2" |
|---|
| 460 | if n > len(self._x): |
|---|
| 461 | raise ValueError, "n must be at most %s"%len(self._x) |
|---|
| 462 | try: |
|---|
| 463 | return self.__qn[n+2] |
|---|
| 464 | except AttributeError: |
|---|
| 465 | self.__qn = [1, 0, 1] |
|---|
| 466 | except IndexError: |
|---|
| 467 | pass |
|---|
| 468 | for k in range(len(self.__qn), n+3): |
|---|
| 469 | self.__qn.append(self._x[k-2]*self.__qn[k-1] + self.__qn[k-2]) |
|---|
| 470 | return self.__qn[n+2] |
|---|
| 471 | |
|---|
| 472 | def _rational_(self): |
|---|
| 473 | """ |
|---|
| 474 | EXAMPLES: |
|---|
| 475 | sage: a = CFF(-17/389); a |
|---|
| 476 | [-1, 1, 21, 1, 7, 2] |
|---|
| 477 | sage: a._rational_() |
|---|
| 478 | -17/389 |
|---|
| 479 | sage: QQ(a) |
|---|
| 480 | -17/389 |
|---|
| 481 | """ |
|---|
| 482 | try: |
|---|
| 483 | return self.__rational |
|---|
| 484 | except AttributeError: |
|---|
| 485 | r = convergents(self._x)[-1] |
|---|
| 486 | self.__rational =r |
|---|
| 487 | return r |
|---|
| 488 | |
|---|
| 489 | def value(self): |
|---|
| 490 | """ |
|---|
| 491 | EXAMPLES: |
|---|
| 492 | sage: a = CFF(-17/389); a |
|---|
| 493 | [-1, 1, 21, 1, 7, 2] |
|---|
| 494 | sage: a.value() |
|---|
| 495 | -17/389 |
|---|
| 496 | sage: QQ(a) |
|---|
| 497 | -17/389 |
|---|
| 498 | """ |
|---|
| 499 | return self._rational_() |
|---|
| 500 | |
|---|
| 501 | def numerator(self): |
|---|
| 502 | """ |
|---|
| 503 | EXAMPLES: |
|---|
| 504 | sage: a = CFF(-17/389); a |
|---|
| 505 | [-1, 1, 21, 1, 7, 2] |
|---|
| 506 | sage: a.numerator() |
|---|
| 507 | -17 |
|---|
| 508 | """ |
|---|
| 509 | return self._rational_().numerator() |
|---|
| 510 | |
|---|
| 511 | def denominator(self): |
|---|
| 512 | """ |
|---|
| 513 | EXAMPLES: |
|---|
| 514 | sage: a = CFF(-17/389); a |
|---|
| 515 | [-1, 1, 21, 1, 7, 2] |
|---|
| 516 | sage: a.denominator() |
|---|
| 517 | 389 |
|---|
| 518 | """ |
|---|
| 519 | return self._rational_().denominator() |
|---|
| 520 | |
|---|
| 521 | def __int__(self): |
|---|
| 522 | """ |
|---|
| 523 | EXAMPLES: |
|---|
| 524 | sage: a = CFF(-17/389); a |
|---|
| 525 | [-1, 1, 21, 1, 7, 2] |
|---|
| 526 | sage: int(a) |
|---|
| 527 | -1 |
|---|
| 528 | """ |
|---|
| 529 | return int(self._rational_()) |
|---|
| 530 | |
|---|
| 531 | def __long__(self): |
|---|
| 532 | """ |
|---|
| 533 | EXAMPLES: |
|---|
| 534 | sage: a = CFF(-17/389); a |
|---|
| 535 | [-1, 1, 21, 1, 7, 2] |
|---|
| 536 | sage: long(a) |
|---|
| 537 | -1L |
|---|
| 538 | """ |
|---|
| 539 | return long(self._rational_()) |
|---|
| 540 | |
|---|
| 541 | def __float__(self): |
|---|
| 542 | """ |
|---|
| 543 | EXAMPLES: |
|---|
| 544 | sage: a = CFF(-17/389); a |
|---|
| 545 | [-1, 1, 21, 1, 7, 2] |
|---|
| 546 | sage: float(a) |
|---|
| 547 | -0.043701799485861177 |
|---|
| 548 | """ |
|---|
| 549 | return float(self._rational_()) |
|---|
| 550 | |
|---|
| 551 | def _add_(self, right): |
|---|
| 552 | """ |
|---|
| 553 | EXAMPLES: |
|---|
| 554 | sage: a = CFF(-17/389) |
|---|
| 555 | sage: b = CFF(1/389) |
|---|
| 556 | sage: c = a+b; c |
|---|
| 557 | [-1, 1, 23, 3, 5] |
|---|
| 558 | sage: c.value() |
|---|
| 559 | -16/389 |
|---|
| 560 | """ |
|---|
| 561 | return ContinuedFraction(self.parent(), |
|---|
| 562 | self._rational_() + right._rational_()) |
|---|
| 563 | |
|---|
| 564 | def _sub_(self, right): |
|---|
| 565 | """ |
|---|
| 566 | EXAMPLES: |
|---|
| 567 | sage: a = CFF(-17/389) |
|---|
| 568 | sage: b = CFF(1/389) |
|---|
| 569 | sage: c = a - b; c |
|---|
| 570 | [-1, 1, 20, 1, 1, 1, 1, 3] |
|---|
| 571 | sage: c.value() |
|---|
| 572 | -18/389 |
|---|
| 573 | """ |
|---|
| 574 | return ContinuedFraction(self.parent(), |
|---|
| 575 | self._rational_() - right._rational_()) |
|---|
| 576 | |
|---|
| 577 | def _mul_(self, right): |
|---|
| 578 | """ |
|---|
| 579 | EXAMPLES: |
|---|
| 580 | sage: a = CFF(-17/389) |
|---|
| 581 | sage: b = CFF(1/389) |
|---|
| 582 | sage: c = a * b; c |
|---|
| 583 | [-1, 1, 8900, 4, 4] |
|---|
| 584 | sage: c.value(), (-1/389)*(17/389) |
|---|
| 585 | (-17/151321, -17/151321) |
|---|
| 586 | """ |
|---|
| 587 | return ContinuedFraction(self.parent(), |
|---|
| 588 | self._rational_() * right._rational_()) |
|---|
| 589 | |
|---|
| 590 | def _div_(self, right): |
|---|
| 591 | """ |
|---|
| 592 | EXAMPLES: |
|---|
| 593 | sage: a = CFF(-17/389) |
|---|
| 594 | sage: b = CFF(1/389) |
|---|
| 595 | sage: c = a / b; c |
|---|
| 596 | [-17] |
|---|
| 597 | sage: c.value(), (17/389) / (-1/389) |
|---|
| 598 | (-17, -17) |
|---|
| 599 | """ |
|---|
| 600 | return ContinuedFraction(self.parent(), |
|---|
| 601 | self._rational_() / right._rational_()) |
|---|
| 602 | |
|---|
| 603 | def __cmp__(self, right): |
|---|
| 604 | """ |
|---|
| 605 | EXAMPLES: |
|---|
| 606 | sage: a = CFF(-17/389) |
|---|
| 607 | sage: b = CFF(1/389) |
|---|
| 608 | sage: a < b |
|---|
| 609 | True |
|---|
| 610 | sage: QQ(a) < QQ(b) |
|---|
| 611 | True |
|---|
| 612 | sage: QQ(a) |
|---|
| 613 | -17/389 |
|---|
| 614 | sage: QQ(b) |
|---|
| 615 | 1/389 |
|---|
| 616 | """ |
|---|
| 617 | return cmp(self._rational_(), right._rational_()) |
|---|
| 618 | |
|---|
| 619 | def _latex_(self): |
|---|
| 620 | """ |
|---|
| 621 | EXAMPLES: |
|---|
| 622 | sage: a = CFF(-17/389) |
|---|
| 623 | sage: latex(a) |
|---|
| 624 | -1+ \frac{\displaystyle 1}{\displaystyle 1+ \frac{\displaystyle 1}{\displaystyle 21+ \frac{\displaystyle 1}{\displaystyle 1+ \frac{\displaystyle 1}{\displaystyle 7+ \frac{\displaystyle 1}{\displaystyle 2}}}}} |
|---|
| 625 | """ |
|---|
| 626 | v = self._x |
|---|
| 627 | if len(v) == 0: |
|---|
| 628 | return '0' |
|---|
| 629 | s = str(v[0]) |
|---|
| 630 | for i in range(1,len(v)): |
|---|
| 631 | s += '+ \\frac{\\displaystyle 1}{\\displaystyle %s'%v[i] |
|---|
| 632 | s += '}'*(len(v)-1) |
|---|
| 633 | return s |
|---|
| 634 | |
|---|
| 635 | def sqrt(self, prec=53, all=False): |
|---|
| 636 | """ |
|---|
| 637 | Return continued fraction approximation to square root of the |
|---|
| 638 | value of this continued fraction. |
|---|
| 639 | |
|---|
| 640 | INPUT: |
|---|
| 641 | prec -- integer (default: 53) precision of square root |
|---|
| 642 | that is approximated |
|---|
| 643 | all -- bool (default: False); if True, return all square |
|---|
| 644 | roots of self, instead of just one. |
|---|
| 645 | |
|---|
| 646 | EXAMPLES: |
|---|
| 647 | sage: a = CFF(4/19); a |
|---|
| 648 | [0, 4, 1, 3] |
|---|
| 649 | sage: b = a.sqrt(); b |
|---|
| 650 | [0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 15, 2] |
|---|
| 651 | sage: b.value() |
|---|
| 652 | 146231375/318703893 |
|---|
| 653 | sage: float(b.value()^2 - a) |
|---|
| 654 | 4.0935373134057017e-17 |
|---|
| 655 | sage: b = a.sqrt(prec=100); b |
|---|
| 656 | [0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 5] |
|---|
| 657 | sage: b^2 |
|---|
| 658 | [0, 4, 1, 3, 49545773063556658177372134479, 1, 3, 4] |
|---|
| 659 | sage: a.sqrt(all=True) |
|---|
| 660 | [[0, 2, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 15, 2], |
|---|
| 661 | [-1, 1, 1, 5, 1, 1, 2, 1, 16, 1, 2, 1, 1, 5, 4, 5, 1, 1, 2, 1, 15, 2]] |
|---|
| 662 | sage: a = CFF(4/25).sqrt(); a |
|---|
| 663 | [0, 2, 2] |
|---|
| 664 | sage: a.value() |
|---|
| 665 | 2/5 |
|---|
| 666 | """ |
|---|
| 667 | r = self._rational_() |
|---|
| 668 | if r < 0: |
|---|
| 669 | raise ValueError, "self must be positive" |
|---|
| 670 | X = r.sqrt(all=all, prec=prec) |
|---|
| 671 | if not all: |
|---|
| 672 | return ContinuedFraction(self.parent(), X) |
|---|
| 673 | else: |
|---|
| 674 | return [ContinuedFraction(self.parent(), x) for x in X] |
|---|
| 675 | |
|---|
| 676 | def list(self): |
|---|
| 677 | """ |
|---|
| 678 | Return copy of the underlying list of this continued |
|---|
| 679 | fraction. |
|---|
| 680 | |
|---|
| 681 | EXAMPLES: |
|---|
| 682 | sage: a = CFF(e); v = a.list(); v |
|---|
| 683 | [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, 11] |
|---|
| 684 | sage: v[0] = 5 |
|---|
| 685 | sage: a |
|---|
| 686 | [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, 11] |
|---|
| 687 | """ |
|---|
| 688 | return list(self._x) |
|---|
| 689 | |
|---|
| 690 | def __hash__(self): |
|---|
| 691 | """ |
|---|
| 692 | Return hash of self, which is the same as the hash of the value |
|---|
| 693 | of self, as a rational number. |
|---|
| 694 | |
|---|
| 695 | EXAMPLES: |
|---|
| 696 | sage: a = CFF(e) |
|---|
| 697 | sage: hash(a) |
|---|
| 698 | 340185673 |
|---|
| 699 | sage: hash(QQ(a)) |
|---|
| 700 | 340185673 |
|---|
| 701 | """ |
|---|
| 702 | return hash(self._rational_()) |
|---|
| 703 | |
|---|
| 704 | def __invert__(self): |
|---|
| 705 | """ |
|---|
| 706 | Return the multiplicative inverse of self. |
|---|
| 707 | |
|---|
| 708 | EXAMPLES: |
|---|
| 709 | sage: a = CFF(e) |
|---|
| 710 | sage: b = ~a; b |
|---|
| 711 | [0, 2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, 11] |
|---|
| 712 | sage: b*a |
|---|
| 713 | [1] |
|---|
| 714 | """ |
|---|
| 715 | return ContinuedFraction(self.parent(), |
|---|
| 716 | self._rational_().__invert__()) |
|---|
| 717 | |
|---|
| 718 | def __pow__(self, n): |
|---|
| 719 | """ |
|---|
| 720 | Return self to the power of n. |
|---|
| 721 | |
|---|
| 722 | EXAMPLES: |
|---|
| 723 | sage: a = CFF([1,2,3]); a |
|---|
| 724 | [1, 2, 3] |
|---|
| 725 | sage: a^3 |
|---|
| 726 | [2, 1, 10, 1, 4, 1, 4] |
|---|
| 727 | sage: QQ(a)^3 == QQ(a^3) |
|---|
| 728 | True |
|---|
| 729 | sage: a^(-3) |
|---|
| 730 | [0, 2, 1, 10, 1, 4, 1, 4] |
|---|
| 731 | sage: QQ(a)^(-3) == QQ(a^(-3)) |
|---|
| 732 | True |
|---|
| 733 | """ |
|---|
| 734 | return ContinuedFraction(self.parent(), |
|---|
| 735 | self._rational_()**n) |
|---|
| 736 | |
|---|
| 737 | def __neg__(self): |
|---|
| 738 | """ |
|---|
| 739 | Return additive inverse of self. |
|---|
| 740 | |
|---|
| 741 | EXAMPLES: |
|---|
| 742 | sage: a = CFF(-17/389); a |
|---|
| 743 | [-1, 1, 21, 1, 7, 2] |
|---|
| 744 | sage: -a |
|---|
| 745 | [0, 22, 1, 7, 2] |
|---|
| 746 | sage: QQ(-a) |
|---|
| 747 | 17/389 |
|---|
| 748 | """ |
|---|
| 749 | return ContinuedFraction(self.parent(), |
|---|
| 750 | self._rational_().__neg__()) |
|---|
| 751 | |
|---|
| 752 | def __abs__(self): |
|---|
| 753 | """ |
|---|
| 754 | Return absolute value of self. |
|---|
| 755 | |
|---|
| 756 | EXAMPLES: |
|---|
| 757 | sage: a = CFF(-17/389); a |
|---|
| 758 | [-1, 1, 21, 1, 7, 2] |
|---|
| 759 | sage: abs(a) |
|---|
| 760 | [0, 22, 1, 7, 2] |
|---|
| 761 | sage: QQ(abs(a)) |
|---|
| 762 | 17/389 |
|---|
| 763 | """ |
|---|
| 764 | return ContinuedFraction(self.parent(), |
|---|
| 765 | self._rational_().__abs__()) |
|---|
| 766 | |
|---|
| 767 | def is_one(self): |
|---|
| 768 | """ |
|---|
| 769 | Return True if self is one. |
|---|
| 770 | |
|---|
| 771 | EXAMPLES: |
|---|
| 772 | sage: continued_fraction(1).is_one() |
|---|
| 773 | True |
|---|
| 774 | sage: continued_fraction(2).is_one() |
|---|
| 775 | False |
|---|
| 776 | """ |
|---|
| 777 | return self._rational_().is_one() |
|---|
| 778 | |
|---|
| 779 | def __nonzero__(self): |
|---|
| 780 | """ |
|---|
| 781 | Return False if self is zero. |
|---|
| 782 | |
|---|
| 783 | EXAMPLES: |
|---|
| 784 | sage: continued_fraction(0).is_zero() |
|---|
| 785 | True |
|---|
| 786 | sage: continued_fraction(1).is_zero() |
|---|
| 787 | False |
|---|
| 788 | """ |
|---|
| 789 | return not self._rational_().is_zero() |
|---|
| 790 | |
|---|
| 791 | def _pari_(self): |
|---|
| 792 | """ |
|---|
| 793 | Return PARI list corresponding to this continued fraction. |
|---|
| 794 | |
|---|
| 795 | EXAMPLES: |
|---|
| 796 | sage: c = continued_fraction(0.12345); c |
|---|
| 797 | [0, 8, 9, 1, 21, 1, 1, 4, 1] |
|---|
| 798 | sage: pari(c) |
|---|
| 799 | [0, 8, 9, 1, 21, 1, 1, 4, 1] |
|---|
| 800 | """ |
|---|
| 801 | return pari(self._x) |
|---|
| 802 | |
|---|
| 803 | def _interface_init_(self, I=None): |
|---|
| 804 | """ |
|---|
| 805 | Return list representation for other systems corresponding to |
|---|
| 806 | this continued fraction. |
|---|
| 807 | |
|---|
| 808 | EXAMPLES: |
|---|
| 809 | sage: c = continued_fraction(0.12345); c |
|---|
| 810 | [0, 8, 9, 1, 21, 1, 1, 4, 1] |
|---|
| 811 | sage: gp(c) |
|---|
| 812 | [0, 8, 9, 1, 21, 1, 1, 4, 1] |
|---|
| 813 | sage: gap(c) |
|---|
| 814 | [ 0, 8, 9, 1, 21, 1, 1, 4, 1 ] |
|---|
| 815 | sage: maxima(c) |
|---|
| 816 | [0,8,9,1,21,1,1,4,1] |
|---|
| 817 | """ |
|---|
| 818 | return str(self._x) |
|---|
| 819 | |
|---|
| 820 | |
|---|
| 821 | CFF = ContinuedFractionField_class() |
|---|
| 822 | |
|---|
| 823 | def ContinuedFractionField(): |
|---|
| 824 | return CFF |
|---|
| 825 | |
|---|
| 826 | def continued_fraction(x, bits=None): |
|---|
| 827 | return CFF(x, bits=bits) |
|---|
| 828 | |
|---|
| 829 | |
|---|
| 830 | |
|---|
| 831 | |
|---|