import torch
import math


def encode_μ_law(x: torch.Tensor, μ: int = 255, cast: bool = False)\
        -> torch.Tensor:
    """
    Encodes the input tensor element-wise with μ-law encoding

    Args:
        x: tensor
        μ: the size of the encoding (number of possible classes)
        cast: whether to cast to int8

    Returns:

    """
    out = torch.sign(x) * torch.log(1 + μ * torch.abs(x)) / math.log(1 + μ)
    out = torch.floor(out * math.ceil(μ / 2))
    if cast:
        out = out.type(torch.int8)
    return out