interp() in Micropython ohne ulab

Wer mal schnell ein Äquivalent für die numpy-Funktion interp() benötigt, aber nicht direkt ulab einkompilieren will, dem/der kann ich hier ein Pythonschnipsel anbieten, das die gleiche Aufgaben in reinem Python übernimmt:

def interp(x, xp, fp, left=None, right=None):
    """Interp() re-implementation in pure python"""
    if isinstance(x, (int, float)):
        x = (x, )  # Create interable from single number input
    l = len(xp)
    if l < 2 or l != len(fp):
        raise ValueError('X-coordinates and y-coordinates must be of equal \
            length, greater then two. ')
    r = []  # Output 
    for xv in x:
        # Find xp-values to interpolate between
        y = 0.0
        if xv < xp[0]:
            y = fp[0] if left is None else left
        elif xv > xp[-1]:
            y = fp[-1] if right is None else right
        else:
            il = 0  # index left,
            ir = d = l-1  # index right, difference
            # Split remaining index range in half until the interpolation
            #  data pair is found
            while d > 1:
                # Integer division for center index (between il and ir)
                ic = (il + ir) // 2
                if xv <= xp[ic]:
                    ir = ic  # Go left in xp-values
                else:
                    il = ic  # Go right in xp-values
                d = ir - il
            # Last step: Linear interpolation for xv between
            # two xf[il] and xf[ir]
            y = float(fp[il] + (xv - xp[il]) * (fp[ir] - fp[il]) / \
                (xp[ir] - xp[il]))
        r.append(y)
    return r if len(r) > 1 else r[0]

Und das garnicht mal so langsam. Mit einem Raspberry Pi Pico W komme ich auf über 13.000 Interpolationen die Sekunde – bei einer Listengröße von 2500 Elementen. Das ist schon eine ordentliche Leistung.

Dieser Beitrag wurde unter Computer abgelegt und mit , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert