def mul(*args):
    """Polynomial multiplication."""
    if len(args) > 2:
        return add(args[0], add(args[1], args[1:]))

    if len(args) == 1:
        return args[0]

    part1, part2 = args

    if not isinstance(part2, Poly):

        if isinstance(part2, (float, int)):
            part2 = np.asarray(part2)

        if not part2.shape:
            core = part1.A.copy()
            dtype = chaospy.poly.typing.dtyping(
                part1.dtype, part2.dtype)
            for key in part1.keys:
                core[key] = np.asarray(core[key]*part2, dtype)
            return Poly(core, part1.dim, part1.shape, dtype)

        part2 = Poly(part2)

    if part2.dim > part1.dim:
        part1 = chaospy.dimension.setdim(part1, part2.dim)

    elif part2.dim < part1.dim:
        part2 = chaospy.dimension.setdim(part2, part1.dim)

    if np.prod(part1.shape) >= np.prod(part2.shape):
        shape = part1.shape
    else:
        shape = part2.shape

    dtype = chaospy.poly.typing.dtyping(part1.dtype, part2.dtype)
    if part1.dtype != part2.dtype:

        if part1.dtype == dtype:
            part2 = chaospy.poly.typing.asfloat(part2)

        else:
            part1 = chaospy.poly.typing.asfloat(part1)

    core = {}
    for idx1 in part2.A:
        for idx2 in part1.A:
            key = tuple(np.array(idx1) + np.array(idx2))
            core[key] = np.asarray(
                core.get(key, 0) + part2.A[idx1]*part1.A[idx2])
    core = {key: value for key, value in core.items() if np.any(value)}

    out = Poly(core, part1.dim, shape, dtype)
    return out
Polynomial multiplication.