def d_scalar_fun(*args): return to_scalar(grad(scalar_fun, argnum=i)(*args))
def scalar_fun(*new_args): full_args = list(args) for i, argnum in enumerate(argnums): full_args[argnum] = new_args[i] return to_scalar(fun(*full_args, **kwargs))
def scalar_args_fun(*new_args): full_args = list(args) for i, argnum in enumerate(argnums): wrt_flat, unflatten = flatten(wrt_args[i]) full_args[argnum] = unflatten(wrt_flat + new_args[i] * rand_vecs[i]) return to_scalar(fun(*full_args, **kwargs))