import torch
from torch.utils.cpp_extension import load_inline

source = """
#include <torch/extension.h>
#include <cuda_runtime.h>

__global__ void relu_square_kernel(const float* x, float* y, long long size) {
    long long idx = blockIdx.x * blockDim.x + threadIdx.x;
    long long stride = blockDim.x * gridDim.x;
    for (long long i = idx; i < size; i += stride) {
        float v = x[i] > 0.0f ? x[i] : 0.0f;
        y[i] = v * v;
    }
}

torch::Tensor relu_square_cuda(torch::Tensor x) {
    auto x_contig = x.contiguous();
    auto y = torch::empty_like(x_contig);
    long long total = x_contig.numel();
    int block = 512;
    long long grid = (total + block - 1) / block;
    grid = grid > 65535 ? 65535 : grid;
    relu_square_kernel<<<(int)grid, block>>>(x_contig.data_ptr<float>(), y.data_ptr<float>(), total);
    return y;
}
"""

cpp_source = """
torch::Tensor relu_square_cuda(torch::Tensor x);
"""

ops = load_inline(
    name="relu_square",
    cpp_sources=cpp_source,
    cuda_sources=source,
    functions=["relu_square_cuda"],
    verbose=True
)

class ModelNew(torch.nn.Module):
    def __init__(self):
        super(ModelNew, self).__init__()
        self.ops = ops

    def forward(self, x):
        return self.ops.relu_square_cuda(x)
