| 385 | |
| 386 | |
| 387 | class RealEncoder(AbstractItemEncoder): |
| 388 | supportIndefLenMode = False |
| 389 | binEncBase = 2 # set to None to choose encoding base automatically |
| 390 | |
| 391 | @staticmethod |
| 392 | def _dropFloatingPoint(m, encbase, e): |
| 393 | ms, es = 1, 1 |
| 394 | if m < 0: |
| 395 | ms = -1 # mantissa sign |
| 396 | |
| 397 | if e < 0: |
| 398 | es = -1 # exponent sign |
| 399 | |
| 400 | m *= ms |
| 401 | |
| 402 | if encbase == 8: |
| 403 | m *= 2 ** (abs(e) % 3 * es) |
| 404 | e = abs(e) // 3 * es |
| 405 | |
| 406 | elif encbase == 16: |
| 407 | m *= 2 ** (abs(e) % 4 * es) |
| 408 | e = abs(e) // 4 * es |
| 409 | |
| 410 | while True: |
| 411 | if int(m) != m: |
| 412 | m *= encbase |
| 413 | e -= 1 |
| 414 | continue |
| 415 | break |
| 416 | |
| 417 | return ms, int(m), encbase, e |
| 418 | |
| 419 | def _chooseEncBase(self, value): |
| 420 | m, b, e = value |
| 421 | encBase = [2, 8, 16] |
| 422 | if value.binEncBase in encBase: |
| 423 | return self._dropFloatingPoint(m, value.binEncBase, e) |
| 424 | |
| 425 | elif self.binEncBase in encBase: |
| 426 | return self._dropFloatingPoint(m, self.binEncBase, e) |
| 427 | |
| 428 | # auto choosing base 2/8/16 |
| 429 | mantissa = [m, m, m] |
| 430 | exponent = [e, e, e] |
| 431 | sign = 1 |
| 432 | encbase = 2 |
| 433 | e = float('inf') |
| 434 | |
| 435 | for i in range(3): |
| 436 | (sign, |
| 437 | mantissa[i], |
| 438 | encBase[i], |
| 439 | exponent[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponent[i]) |
| 440 | |
| 441 | if abs(exponent[i]) < abs(e) or (abs(exponent[i]) == abs(e) and mantissa[i] < m): |
| 442 | e = exponent[i] |
| 443 | m = int(mantissa[i]) |
| 444 | encbase = encBase[i] |