def compute_hulls(S, fS, domain):
assert(len(S) == len(fS))<EOL>assert(len(domain) == <NUM_LIT:2>)<EOL>lower_hull = []<EOL>for li in range(len(S) - <NUM_LIT:1>):<EOL><INDENT>m = (fS[li + <NUM_LIT:1>] - fS[li]) / (S[li + <NUM_LIT:1>] - S[li])<EOL>b = fS[li] - m * S[li]<EOL>left = S[li]<EOL>right = S[li + <NUM_LIT:1>]<EOL>lower_hull.append(HullNode(m=m, b=b, left=left, right=right))<EOL><DEDENT>n_upper_segments = <NUM_LIT:2> * (len(S) - <NUM_LIT:2>) + isinf(domain[<NUM_LIT:0>]) + isinf(domain[<NUM_LIT:1>])<EOL>upper_hull = []<EOL>if isinf(domain[<NUM_LIT:0>]):<EOL><INDENT>m = (fS[<NUM_LIT:1>] - fS[<NUM_LIT:0>]) / (S[<NUM_LIT:1>] - S[<NUM_LIT:0>])<EOL>b = fS[<NUM_LIT:0>] - m * S[<NUM_LIT:0>]<EOL>pr = compute_segment_log_prob(float("<STR_LIT>"), S[<NUM_LIT:0>], m, b)<EOL>upper_hull.append(<EOL>HullNode(m=m, b=b, pr=pr, left=float("<STR_LIT>"), right=S[<NUM_LIT:0>])<EOL>)<EOL><DEDENT>m = (fS[<NUM_LIT:2>] - fS[<NUM_LIT:1>]) / (S[<NUM_LIT:2>] - S[<NUM_LIT:1>])<EOL>b = fS[<NUM_LIT:1>] - m * S[<NUM_LIT:1>]<EOL>pr = compute_segment_log_prob(S[<NUM_LIT:0>], S[<NUM_LIT:1>], m, b)<EOL>upper_hull.append(HullNode(m=m, b=b, pr=pr, left=S[<NUM_LIT:0>], right=S[<NUM_LIT:1>]))<EOL>for li in range(<NUM_LIT:1>, len(S) - <NUM_LIT:2>):<EOL><INDENT>m1 = (fS[li] - fS[li - <NUM_LIT:1>]) / (S[li] - S[li - <NUM_LIT:1>])<EOL>b1 = fS[li] - m1 * S[li]<EOL>m2 = (fS[li + <NUM_LIT:2>] - fS[li + <NUM_LIT:1>]) / (S[li + <NUM_LIT:2>] - S[li + <NUM_LIT:1>])<EOL>b2 = fS[li + <NUM_LIT:1>] - m2 * S[li + <NUM_LIT:1>]<EOL>if isinf(m1) and isinf(m2):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>dx1 = S[li] - S[li - <NUM_LIT:1>]<EOL>df1 = fS[li] - fS[li - <NUM_LIT:1>]<EOL>dx2 = S[li + <NUM_LIT:2>] - S[li + <NUM_LIT:1>]<EOL>df2 = fS[li + <NUM_LIT:2>] - fS[li + <NUM_LIT:1>]<EOL>f1 = fS[li]<EOL>f2 = fS[li + <NUM_LIT:1>]<EOL>x1 = S[li]<EOL>x2 = S[li + <NUM_LIT:1>]<EOL>ix = ((f1 * dx1 - df1 * x1) * dx2 - (f2 * dx2 - df2 * x2) * dx1) / (df2 * dx1 - df1 * dx2)<EOL>if isinf(m1) or abs(m1 - m2) < <NUM_LIT> ** <NUM_LIT:8> * eps(m1):<EOL><INDENT>ix = S[li]<EOL>pr1 = float("<STR_LIT>")<EOL>pr2 = compute_segment_log_prob(ix, S[li + <NUM_LIT:1>], m2, b2)<EOL><DEDENT>elif isinf(m2):<EOL><INDENT>ix = S[li + <NUM_LIT:1>]<EOL>pr1 = compute_segment_log_prob(S[li], ix, m1, b1)<EOL>pr2 = float("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>if isinf(ix):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if abs(ix - S[li]) < <NUM_LIT> ** <NUM_LIT:12> * eps(S[li]):<EOL><INDENT>ix = S[li]<EOL><DEDENT>elif abs(ix - S[li + <NUM_LIT:1>]) < <NUM_LIT>**<NUM_LIT:12> * eps(S[li + <NUM_LIT:1>]):<EOL><INDENT>ix = S[li + <NUM_LIT:1>]<EOL><DEDENT>if ix < S[li] or ix > S[li + <NUM_LIT:1>]:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>pr1 = compute_segment_log_prob(S[li], ix, m1, b1)<EOL>pr2 = compute_segment_log_prob(ix, S[li + <NUM_LIT:1>], m2, b2)<EOL>upper_hull.append(HullNode(m=m1, b=b1, pr=pr1, left=S[li], right=ix))<EOL>upper_hull.append(HullNode(m=m2, b=b2, pr=pr2, left=ix, right=S[li + <NUM_LIT:1>]))<EOL><DEDENT><DEDENT>m = (fS[-<NUM_LIT:2>] - fS[-<NUM_LIT:3>]) / float(S[-<NUM_LIT:2>] - S[-<NUM_LIT:3>])<EOL>b = fS[-<NUM_LIT:2>] - m * S[-<NUM_LIT:2>]<EOL>pr = compute_segment_log_prob(S[-<NUM_LIT:2>], S[-<NUM_LIT:1>], m, b)<EOL>upper_hull.append(HullNode(m=m, b=b, pr=pr, left=S[-<NUM_LIT:2>], right=S[-<NUM_LIT:1>]))<EOL>if isinf(domain[<NUM_LIT:1>]):<EOL><INDENT>m = (fS[-<NUM_LIT:1>] - fS[-<NUM_LIT:2>]) / (S[-<NUM_LIT:1>] - S[-<NUM_LIT:2>])<EOL>b = fS[-<NUM_LIT:1>] - m * S[-<NUM_LIT:1>]<EOL>pr = compute_segment_log_prob(S[-<NUM_LIT:1>], float("<STR_LIT>"), m, b)<EOL>upper_hull.append(<EOL>HullNode(m=m, b=b, pr=pr, left=S[-<NUM_LIT:1>], right=float("<STR_LIT>"))<EOL>)<EOL><DEDENT>normalized_probabilities = exp_normalize(<EOL>asarray([node.pr for node in upper_hull])<EOL>)<EOL>for node, probability in zip(upper_hull, normalized_probabilities):<EOL><INDENT>node.pr = probability<EOL><DEDENT>assert(len(lower_hull) == len(S) - <NUM_LIT:1>)<EOL>assert(len(upper_hull) == n_upper_segments)<EOL>return lower_hull, upper_hull<EOL>
(Re-)compute upper and lower hull given
the segment points `S` with function values
`fS` and the `domain` of the logpdf.

Parameters
----------
S : np.ndarray (N, 1)
   Straight-line segment points accumulated thus far.

fS : tuple
    Value of the `logpdf` under sampling for each
    of the given segment points in `S`.

domain : Tuple[float, float]
    Domain of `logpdf`.
    May be unbounded on either or both sides,
    in which case `(float("-inf"), float("inf"))`
    would be passed.
    If this domain is unbounded to the left,
    the derivative of the logpdf
    for x<= a must be positive.
    If this domain is unbounded to the right                  the derivative of the logpdf for x>=b
    must be negative.

Returns
----------
lower_hull: List[arspy.hull.HullNode]
upper_hull: List[arspy.hull.HullNode]