fork(1) download
  1. # Trying to figure out the behavior of numpy.interp.
  2.  
  3. import math
  4. import bisect
  5.  
  6. def to_float(iterable):
  7. return list(map(float, iterable))
  8.  
  9. def lerp(a, b, t):
  10. return (1 - t) * a + b * t
  11.  
  12. def invlerp(x, a, b):
  13. if math.isclose(a, b):
  14. return 0.5
  15. return (x - a) / (b - a)
  16.  
  17. def interp(x, xp, fp, left=None, right=None):
  18. """
  19. Linear interpolation for monotonically increasing sample points.
  20. """
  21. n = len(xp)
  22.  
  23. if n != len(fp):
  24. raise ValueError('fp and xp are not of the same length.')
  25. if n == 0:
  26. return
  27.  
  28. xp = to_float(xp)
  29. fp = to_float(fp)
  30.  
  31. if left is None:
  32. left = fp[0]
  33. else:
  34. left = float(left)
  35. if right is None:
  36. right = fp[-1]
  37. else:
  38. right = float(right)
  39.  
  40. last = xp[-1]
  41.  
  42. for y in x:
  43. if y > last:
  44. yield right; continue
  45. i = bisect.bisect(xp, y)
  46. if i == 0:
  47. yield left; continue
  48. j = i-1
  49. k = min(i, n-1)
  50. yield lerp(fp[j], fp[k], invlerp(y, xp[j], xp[k]))
  51.  
  52. # Main.
  53.  
  54. xp = [1, 2, 3]
  55. fp = [3, 2, 0]
  56. x = [0, 0.99, 1, 1.5, 2.73, 3, 3.01, 3.14]
  57.  
  58. print(list(interp([2.5], xp, fp)))
  59. print(list(interp(x, xp, fp)))
  60. print(list(interp(x, xp, fp, left=-99, right=99)))
  61.  
  62. import numpy as np
  63. print(list(np.interp([2.5], xp, fp)))
  64. print(list(np.interp(x, xp, fp)))
  65. print(list(np.interp(x, xp, fp, left=-99, right=99)))
Success #stdin #stdout 0.79s 41600KB
stdin
Standard input is empty
stdout
[1.0]
[3.0, 3.0, 3.0, 2.5, 0.54, 0.0, 0.0, 0.0]
[-99.0, -99.0, 3.0, 2.5, 0.54, 0.0, 99.0, 99.0]
[1.0]
[3.0, 3.0, 3.0, 2.5, 0.54, 0.0, 0.0, 0.0]
[-99.0, -99.0, 3.0, 2.5, 0.54, 0.0, 99.0, 99.0]