import torch
from torch import device
from torch._inductor.select_algorithm import extern_kernels
import triton
import triton.language as tl
from torch._inductor.runtime.triton_heuristics import grid
from torch._C import _cuda_getCurrentRawStream as get_raw_stream
from torch._inductor.runtime.triton_helpers import math as tl_math
from torch.nn import Module
import math
from torch.nn import Parameter
import torch.nn.functional as F
from torch.nn.modules.utils import _pair
assert_size_stride = torch._C._dynamo.guards.assert_size_stride
empty_strided_cuda = torch._C._dynamo.guards._empty_strided_cuda


@triton.jit
def triton_poi_fused_add_exp_mul_0(in_ptr0, in_ptr1, in_ptr2, out_ptr0,
    xnumel, XBLOCK: tl.constexpr):
    xnumel = 256
    xoffset = tl.program_id(0) * XBLOCK
    xindex = xoffset + tl.arange(0, XBLOCK)[:]
    xmask = xindex < xnumel
    x0 = xindex
    tmp0 = tl.load(in_ptr0 + x0, xmask)
    tmp1 = tl.load(in_ptr1 + x0, xmask)
    tmp3 = tl.load(in_ptr2 + x0, xmask)
    tmp2 = tl_math.exp(tmp1)
    tmp4 = tmp2 * tmp3
    tmp5 = tmp0 + tmp4
    tl.store(out_ptr0 + x0, tmp5, xmask)


@triton.jit
def triton_poi_fused_add_convolution_exp_mul_1(in_ptr0, in_ptr1, in_ptr2,
    out_ptr0, xnumel, XBLOCK: tl.constexpr):
    xnumel = 4
    xoffset = tl.program_id(0) * XBLOCK
    xindex = xoffset + tl.arange(0, XBLOCK)[:]
    xmask = xindex < xnumel
    x0 = xindex
    tmp0 = tl.load(in_ptr0 + x0, xmask)
    tmp1 = tl.load(in_ptr1 + x0, xmask)
    tmp3 = tl.load(in_ptr2 + x0, xmask)
    tmp2 = tl_math.exp(tmp1)
    tmp4 = tmp2 * tmp3
    tmp5 = tmp0 + tmp4
    tl.store(out_ptr0 + x0, tmp5, xmask)


@triton.jit
def triton_poi_fused_add_convolution_exp_mul_2(in_out_ptr0, in_ptr0, xnumel,
    XBLOCK: tl.constexpr):
    xnumel = 16
    xoffset = tl.program_id(0) * XBLOCK
    xindex = xoffset + tl.arange(0, XBLOCK)[:]
    xmask = xindex < xnumel
    x2 = xindex
    x0 = xindex % 4
    tmp0 = tl.load(in_out_ptr0 + x2, xmask)
    tmp1 = tl.load(in_ptr0 + x0, xmask, eviction_policy='evict_last')
    tmp2 = tmp0 + tmp1
    tl.store(in_out_ptr0 + x2, tmp2, xmask)


def call(args):
    primals_1, primals_2, primals_3, primals_4, primals_5 = args
    args.clear()
    assert_size_stride(primals_1, (4, 4, 4, 4), (64, 16, 4, 1))
    assert_size_stride(primals_2, (4, 4, 4, 4), (64, 16, 4, 1))
    assert_size_stride(primals_3, (4,), (1,))
    assert_size_stride(primals_4, (4,), (1,))
    assert_size_stride(primals_5, (4, 4, 4, 4), (64, 16, 4, 1))
    with torch.cuda._DeviceGuard(0):
        torch.cuda.set_device(0)
        buf0 = torch.ops.aten.randn.default([4, 4, 4, 4], dtype=torch.
            float32, device=device(type='cuda', index=0), pin_memory=False)
        buf1 = buf0
        del buf0
        buf2 = empty_strided_cuda((4, 4, 4, 4), (64, 16, 4, 1), torch.float32)
        get_raw_stream(0)
        triton_poi_fused_add_exp_mul_0[grid(256)](primals_1, primals_2,
            buf1, buf2, 256, XBLOCK=256, num_warps=4, num_stages=1)
        del primals_1
        buf3 = torch.ops.aten.randn.default([4], dtype=torch.float32,
            device=device(type='cuda', index=0), pin_memory=False)
        buf4 = buf3
        del buf3
        buf5 = empty_strided_cuda((4,), (1,), torch.float32)
        triton_poi_fused_add_convolution_exp_mul_1[grid(4)](primals_3,
            primals_4, buf4, buf5, 4, XBLOCK=4, num_warps=1, num_stages=1)
        del primals_3
        buf6 = extern_kernels.convolution(primals_5, buf2, stride=(1, 1),
            padding=(0, 0), dilation=(1, 1), transposed=False,
            output_padding=(0, 0), groups=1, bias=None)
        assert_size_stride(buf6, (4, 4, 1, 1), (4, 1, 1, 1))
        buf7 = buf6
        del buf6
        triton_poi_fused_add_convolution_exp_mul_2[grid(16)](buf7, buf5, 16,
            XBLOCK=16, num_warps=1, num_stages=1)
        del buf5
    return buf7, primals_2, primals_4, primals_5, buf1, buf2, buf4


class _BayesConvNd(Module):
    """
    Applies Bayesian Convolution

    Arguments:
        prior_mu (Float): mean of prior normal distribution.
        prior_sigma (Float): sigma of prior normal distribution.

    .. note:: other arguments are following conv of pytorch 1.2.0.
    https://github.com/pytorch/pytorch/blob/master/torch/nn/modules/conv.py
    """
    __constants__ = ['prior_mu', 'prior_sigma', 'stride', 'padding',
        'dilation', 'groups', 'bias', 'padding_mode', 'output_padding',
        'in_channels', 'out_channels', 'kernel_size']

    def __init__(self, prior_mu, prior_sigma, in_channels, out_channels,
        kernel_size, stride, padding, dilation, transposed, output_padding,
        groups, bias, padding_mode):
        super(_BayesConvNd, self).__init__()
        if in_channels % groups != 0:
            raise ValueError('in_channels must be divisible by groups')
        if out_channels % groups != 0:
            raise ValueError('out_channels must be divisible by groups')
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        self.dilation = dilation
        self.transposed = transposed
        self.output_padding = output_padding
        self.groups = groups
        self.padding_mode = padding_mode
        self.prior_mu = prior_mu
        self.prior_sigma = prior_sigma
        self.prior_log_sigma = math.log(prior_sigma)
        if transposed:
            self.weight_mu = Parameter(torch.Tensor(in_channels, 
                out_channels // groups, *kernel_size))
            self.weight_log_sigma = Parameter(torch.Tensor(in_channels, 
                out_channels // groups, *kernel_size))
            self.register_buffer('weight_eps', None)
        else:
            self.weight_mu = Parameter(torch.Tensor(out_channels, 
                in_channels // groups, *kernel_size))
            self.weight_log_sigma = Parameter(torch.Tensor(out_channels, 
                in_channels // groups, *kernel_size))
            self.register_buffer('weight_eps', None)
        if bias is None or bias is False:
            self.bias = False
        else:
            self.bias = True
        if self.bias:
            self.bias_mu = Parameter(torch.Tensor(out_channels))
            self.bias_log_sigma = Parameter(torch.Tensor(out_channels))
            self.register_buffer('bias_eps', None)
        else:
            self.register_parameter('bias_mu', None)
            self.register_parameter('bias_log_sigma', None)
            self.register_buffer('bias_eps', None)
        self.reset_parameters()

    def reset_parameters(self):
        n = self.in_channels
        n *= self.kernel_size[0] ** 2
        stdv = 1.0 / math.sqrt(n)
        self.weight_mu.data.uniform_(-stdv, stdv)
        self.weight_log_sigma.data.fill_(self.prior_log_sigma)
        if self.bias:
            self.bias_mu.data.uniform_(-stdv, stdv)
            self.bias_log_sigma.data.fill_(self.prior_log_sigma)

    def freeze(self):
        self.weight_eps = torch.randn_like(self.weight_log_sigma)
        if self.bias:
            self.bias_eps = torch.randn_like(self.bias_log_sigma)

    def unfreeze(self):
        self.weight_eps = None
        if self.bias:
            self.bias_eps = None

    def extra_repr(self):
        s = (
            '{prior_mu}, {prior_sigma}, {in_channels}, {out_channels}, kernel_size={kernel_size}, stride={stride}'
            )
        if self.padding != (0,) * len(self.padding):
            s += ', padding={padding}'
        if self.dilation != (1,) * len(self.dilation):
            s += ', dilation={dilation}'
        if self.output_padding != (0,) * len(self.output_padding):
            s += ', output_padding={output_padding}'
        if self.groups != 1:
            s += ', groups={groups}'
        if self.bias is False:
            s += ', bias=False'
        return s.format(**self.__dict__)

    def __setstate__(self, state):
        super(_BayesConvNd, self).__setstate__(state)
        if not hasattr(self, 'padding_mode'):
            self.padding_mode = 'zeros'


class BayesConv2dNew(_BayesConvNd):
    """
    Applies Bayesian Convolution for 2D inputs

    Arguments:
        prior_mu (Float): mean of prior normal distribution.
        prior_sigma (Float): sigma of prior normal distribution.

    .. note:: other arguments are following conv of pytorch 1.2.0.
    https://github.com/pytorch/pytorch/blob/master/torch/nn/modules/conv.py
    
    """

    def __init__(self, prior_mu, prior_sigma, in_channels, out_channels,
        kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True,
        padding_mode='zeros'):
        kernel_size = _pair(kernel_size)
        stride = _pair(stride)
        padding = _pair(padding)
        dilation = _pair(dilation)
        super(BayesConv2dNew, self).__init__(prior_mu, prior_sigma,
            in_channels, out_channels, kernel_size, stride, padding,
            dilation, False, _pair(0), groups, bias, padding_mode)

    def conv2d_forward(self, input, weight):
        if self.bias:
            if self.bias_eps is None:
                bias = self.bias_mu + torch.exp(self.bias_log_sigma
                    ) * torch.randn_like(self.bias_log_sigma)
            else:
                bias = self.bias_mu + torch.exp(self.bias_log_sigma
                    ) * self.bias_eps
        else:
            bias = None
        if self.padding_mode == 'circular':
            expanded_padding = (self.padding[1] + 1) // 2, self.padding[1
                ] // 2, (self.padding[0] + 1) // 2, self.padding[0] // 2
            return F.conv2d(F.pad(input, expanded_padding, mode='circular'),
                weight, bias, self.stride, _pair(0), self.dilation, self.groups
                )
        return F.conv2d(input, weight, bias, self.stride, self.padding,
            self.dilation, self.groups)

    def forward(self, input_0):
        primals_1 = self.weight_mu
        primals_2 = self.weight_log_sigma
        primals_3 = self.bias_mu
        primals_4 = self.bias_log_sigma
        primals_5 = input_0
        output = call([primals_1, primals_2, primals_3, primals_4, primals_5])
        return output[0]


Measured latency_ms: 0.071128