| """ sinc(t) := sin(t) / t """ |
| import torch |
| from torch import sin, cos |
|
|
| def sinc1(t): |
| """ sinc1: t -> sin(t)/t """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t[s] ** 2 |
| r[s] = 1 - t2/6*(1 - t2/20*(1 - t2/42)) |
| r[c] = sin(t[c]) / t[c] |
|
|
| return r |
|
|
| def sinc1_dt(t): |
| """ d/dt(sinc1) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t ** 2 |
| r[s] = -t[s]/3*(1 - t2[s]/10*(1 - t2[s]/28*(1 - t2[s]/54))) |
| r[c] = cos(t[c])/t[c] - sin(t[c])/t2[c] |
|
|
| return r |
|
|
| def sinc1_dt_rt(t): |
| """ d/dt(sinc1) / t """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t ** 2 |
| r[s] = -1/3*(1 - t2[s]/10*(1 - t2[s]/28*(1 - t2[s]/54))) |
| r[c] = (cos(t[c]) / t[c] - sin(t[c]) / t2[c]) / t[c] |
|
|
| return r |
|
|
|
|
| def rsinc1(t): |
| """ rsinc1: t -> t/sinc1(t) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t[s] ** 2 |
| r[s] = (((31*t2)/42 + 7)*t2/60 + 1)*t2/6 + 1 |
| r[c] = t[c] / sin(t[c]) |
|
|
| return r |
|
|
| def rsinc1_dt(t): |
| """ d/dt(rsinc1) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t[s] ** 2 |
| r[s] = ((((127*t2)/30 + 31)*t2/28 + 7)*t2/30 + 1)*t[s]/3 |
| r[c] = 1/sin(t[c]) - (t[c]*cos(t[c]))/(sin(t[c])*sin(t[c])) |
|
|
| return r |
|
|
| def rsinc1_dt_csc(t): |
| """ d/dt(rsinc1) / sin(t) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t[s] ** 2 |
| r[s] = t2*(t2*((4*t2)/675 + 2/63) + 2/15) + 1/3 |
| r[c] = (1/sin(t[c]) - (t[c]*cos(t[c]))/(sin(t[c])*sin(t[c]))) / sin(t[c]) |
|
|
| return r |
|
|
|
|
| def sinc2(t): |
| """ sinc2: t -> (1 - cos(t)) / (t**2) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t ** 2 |
| r[s] = 1/2*(1-t2[s]/12*(1-t2[s]/30*(1-t2[s]/56))) |
| r[c] = (1-cos(t[c]))/t2[c] |
|
|
| return r |
|
|
| def sinc2_dt(t): |
| """ d/dt(sinc2) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t ** 2 |
| r[s] = -t[s]/12*(1 - t2[s]/5*(1.0/3 - t2[s]/56*(1.0/2 - t2[s]/135))) |
| r[c] = sin(t[c])/t2[c] - 2*(1-cos(t[c]))/(t2[c]*t[c]) |
|
|
| return r |
|
|
|
|
| def sinc3(t): |
| """ sinc3: t -> (t - sin(t)) / (t**3) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t[s] ** 2 |
| r[s] = 1/6*(1-t2/20*(1-t2/42*(1-t2/72))) |
| r[c] = (t[c]-sin(t[c]))/(t[c]**3) |
|
|
| return r |
|
|
| def sinc3_dt(t): |
| """ d/dt(sinc3) """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t[s] ** 2 |
| r[s] = -t[s]/60*(1 - t2/21*(1 - t2/24*(1.0/2 - t2/165))) |
| r[c] = (3*sin(t[c]) - t[c]*(cos(t[c]) + 2))/(t[c]**4) |
|
|
| return r |
|
|
|
|
| def sinc4(t): |
| """ sinc4: t -> 1/t^2 * (1/2 - sinc2(t)) |
| = 1/t^2 * (1/2 - (1 - cos(t))/t^2) |
| """ |
| e = 0.01 |
| r = torch.zeros_like(t) |
| a = torch.abs(t) |
|
|
| s = a < e |
| c = (s == 0) |
| t2 = t ** 2 |
| r[s] = 1/24*(1-t2/30*(1-t2/56*(1-t2/90))) |
| r[c] = (0.5 - (1 - cos(t))/t2) / t2 |
|
|
|
|
| class Sinc1_autograd(torch.autograd.Function): |
| @staticmethod |
| def forward(ctx, theta): |
| ctx.save_for_backward(theta) |
| return sinc1(theta) |
|
|
| @staticmethod |
| def backward(ctx, grad_output): |
| theta, = ctx.saved_tensors |
| grad_theta = None |
| if ctx.needs_input_grad[0]: |
| grad_theta = grad_output * sinc1_dt(theta).to(grad_output) |
| return grad_theta |
|
|
| Sinc1 = Sinc1_autograd.apply |
|
|
| class RSinc1_autograd(torch.autograd.Function): |
| @staticmethod |
| def forward(ctx, theta): |
| ctx.save_for_backward(theta) |
| return rsinc1(theta) |
|
|
| @staticmethod |
| def backward(ctx, grad_output): |
| theta, = ctx.saved_tensors |
| grad_theta = None |
| if ctx.needs_input_grad[0]: |
| grad_theta = grad_output * rsinc1_dt(theta).to(grad_output) |
| return grad_theta |
|
|
| RSinc1 = RSinc1_autograd.apply |
|
|
| class Sinc2_autograd(torch.autograd.Function): |
| @staticmethod |
| def forward(ctx, theta): |
| ctx.save_for_backward(theta) |
| return sinc2(theta) |
|
|
| @staticmethod |
| def backward(ctx, grad_output): |
| theta, = ctx.saved_tensors |
| grad_theta = None |
| if ctx.needs_input_grad[0]: |
| grad_theta = grad_output * sinc2_dt(theta).to(grad_output) |
| return grad_theta |
|
|
| Sinc2 = Sinc2_autograd.apply |
|
|
| class Sinc3_autograd(torch.autograd.Function): |
| @staticmethod |
| def forward(ctx, theta): |
| ctx.save_for_backward(theta) |
| return sinc3(theta) |
|
|
| @staticmethod |
| def backward(ctx, grad_output): |
| theta, = ctx.saved_tensors |
| grad_theta = None |
| if ctx.needs_input_grad[0]: |
| grad_theta = grad_output * sinc3_dt(theta).to(grad_output) |
| return grad_theta |
|
|
| Sinc3 = Sinc3_autograd.apply |
|
|
|
|
| |
|
|