Advertisement
N3buchadnezzar

PE002

Aug 6th, 2021
383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.97 KB | None | 0 0
  1. import math
  2.  
  3. import timeit
  4. import numpy as np
  5.  
  6. SQRT5 = math.sqrt(5)
  7. GOLDEN_RATIO = (1 + SQRT5) / 2
  8. LOG_5 = math.log(5, GOLDEN_RATIO) / 6
  9.  
  10.  
  11. def largest_even_fib_index(n):
  12.     return int(LOG_5 + math.log(n, GOLDEN_RATIO) / 3)
  13.  
  14.  
  15. def fibonacci(n):
  16.     def fib_inner(n):
  17.         """Returns L[n] and L[n+1]"""
  18.         if n == 0:
  19.             return 2, 1
  20.         m = n >> 1
  21.         u, v = fib_inner(m)
  22.         q = (2, -2)[m & 1]
  23.         u = u * u - q
  24.         v = v * v + q
  25.         if n & 1:
  26.             return v - u, v
  27.         return u, v - u
  28.  
  29.     m = n >> 1
  30.     u, v = fib_inner(m)
  31.     # F[m]
  32.     f = (2 * v - u) // 5
  33.     if n & 1:
  34.         q = (n & 2) - 1
  35.         return v * f - q
  36.     return u * f
  37.  
  38.  
  39. def PE_002(limit=4 * 10 ** 6):
  40.     if limit < 10 ** 25:
  41.         a, b = 0, 2
  42.         while b < limit:
  43.             a, b = b, 4 * b + a
  44.         even_fib_sum = (a + b - 2) // 4
  45.     else:
  46.         n = largest_even_fib_index(limit)
  47.         even_fib_sum = (fibonacci(3 * n + 2) - 1) // 2
  48.     return even_fib_sum
  49.  
  50.  
  51. def sum_even_fib_sublinear(limit=4 * 10 ** 6):
  52.     n = largest_even_fib_index(limit)
  53.     return (fibonacci(3 * n + 2) - 1) // 2
  54.  
  55.  
  56. def sum_even_fib_fast(limit):
  57.     a, b = 0, 2
  58.     while b < limit:
  59.         a, b = b, 4 * b + a
  60.     return (a + b - 2) // 4
  61.  
  62.  
  63. def fib(n):
  64.     a, b = 0, 1
  65.     for _ in range(n):
  66.         a, b = b, a + b
  67.     return a
  68.  
  69.  
  70. def sum_even_fib_naive(limit):
  71.     a, b, total = 0, 1, 0
  72.     while a < limit:
  73.         if a % 2 == 0:
  74.             total += a
  75.         a, b = b, a + b
  76.     return total
  77.  
  78.  
  79. if __name__ == "__main__":
  80.  
  81.     num = 10 ** 3
  82.     rep = 100
  83.     print(f" Power    Naive      Fast    Sublinear")
  84.     for power in range(0, 50, 5):
  85.         limit = 4 * 10 ** power
  86.  
  87.         reps1 = timeit.repeat(
  88.             repeat=rep,
  89.             number=num,
  90.             stmt=f"sum_even_fib_naive({limit})",
  91.             setup="from __main__ import sum_even_fib_naive",
  92.         )
  93.  
  94.         reps2 = timeit.repeat(
  95.             repeat=rep,
  96.             number=100,
  97.             stmt=f"sum_even_fib_fast({limit})",
  98.             setup="from __main__ import sum_even_fib_fast",
  99.         )
  100.  
  101.         reps3 = timeit.repeat(
  102.             repeat=rep,
  103.             number=100,
  104.             stmt=f"sum_even_fib_sublinear({limit})",
  105.             setup="from __main__ import sum_even_fib_sublinear",
  106.         )
  107.  
  108.         reps4 = timeit.repeat(
  109.             repeat=rep,
  110.             number=100,
  111.             stmt=f"PE_002({limit})",
  112.             setup="from __main__ import PE_002",
  113.         )
  114.  
  115.         # taking the median might be better, since I suspect the distribution of times will
  116.         # be heavily skewed
  117.         naive, fast, sublinear, euler002 = [
  118.             np.mean(reps) for reps in [reps1, reps2, reps3, reps4]
  119.         ]
  120.         print(
  121.             f" {power:>3}    {naive:>.2e}     {int(naive/fast):>3}       {int(naive/sublinear):>3}       {int(naive/euler002):>3}    "
  122.         )
  123.     # if fast > sublinear:
  124.     #     break
  125.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement