from src import get_cache_size
from src.multiples import factory as multiples_factory
from src.primes import factory as primes_factory
from src.primesgen import Eratosthenes
from src.primesgenseg import SegmentedEratosthenes

segment_size = get_cache_size()


def test_84_max_val_9_segment_size(): assert_len_at(84, 9)


def test_130_max_val_9_segment_size(): assert_len_at(130, 9)


def test_segment_boundaries():
    seg_sizes = [int(.1 * segment_size), int(.25 * segment_size), int(.5 * segment_size), int(.75 * segment_size),
                 segment_size, segment_size * 2]
    for seg_size in seg_sizes:
        assert_len_at(seg_size - 1, seg_size)
    for i in [-1, 0, 1, 2]:
        for seg_size in seg_sizes:
            assert_len_at(i, seg_size)
    for seg_size in seg_sizes:
        for m in range(2, 5):
            assert_len_at((m - 1) * seg_size, seg_size)
            assert_len_at((m - 1) * seg_size + 1, seg_size)


def test_100_000(): assert_len_at(100_000, segment_size)


def test_120_001(): assert_len_at(120_001, segment_size)


def assert_segment(segment_num):
    for i in range((segment_num - 1) * segment_size, segment_num * segment_size):
        assert_len_at(i, segment_size)


def assert_len_at(max_val, seg_size):
    c_primes = Eratosthenes().primes(max_val)
    c_len = len(c_primes)
    c_primes.clear()

    s_primes = SegmentedEratosthenes(seg_size, primes_factory(None), multiples_factory(max_val)).primes(max_val)
    s_len = len(s_primes)
    s_primes.clear()

    assert s_len == c_len, f'{max_val}, lengths differ ({s_len}, {c_len})'
