
import sys

__author__ = 'klinger'

LOWER_START = -2
UPPER_START = 20


def fever_lambda_optimizer(p_calculator, p_target, accuracy=.03, max_iter=100):
    """
    Parameters
    ----------

    p_calculator: callable

    p_target: float
        target value in [0,1]
    """
    # put function in nicer form
    pc = lambda x:  p_calculator(10**(-x))

    l_lower = LOWER_START
    l_upper = UPPER_START

    l_next = UPPER_START
    p = pc(l_next)
    iter_nr = 0

    while ((abs(p / p_target - 1) > accuracy)
           and (l_upper > l_lower)
           and iter_nr < max_iter):
        iter_nr += 1
        l_next = (l_lower+l_upper)/2
        p = pc(l_next)
        if p > p_target:
            l_upper = max(l_next, l_lower)
        else:
            l_lower = min(l_next, l_upper)


    # print('p:', p, 'p_target:', p_target, 'iter_nr:', iter_nr, 'max_iter', max_iter, 'low:', l_lower, 'up:', l_upper)
    if iter_nr >= max_iter:
        print('Warning: fever_lambda_optimizer: Max nr of iterations exceeded.', file=sys.stderr)
    if l_upper <= l_lower:
        print('fever_lambda_optimizer: upper bound <= lower bound.', file=sys.stderr)
    if iter_nr == 0:
        print('fever_lambda_optimizer:Initial parameter in fever lambda optimization taken.', file=sys.stderr)

    return 10**(-l_next)




