def method_anurupyena_depthwise():
    """
    Anurupyena: Proportional scaling.
    Use depthwise separable convolution (inspired by proportional decomposition).
    """
    # Depthwise: One channel per group
    w_dw = w.view(K, 1, kH, kW)  # Already grouped by channel
    
    # Pointwise: 1x1 convolution to mix channels
    w_pw = torch.eye(K, C, dtype=torch.float32).view(K, C, 1, 1)
    
    # Approximation: depthwise only (fast but approximate)
    # True separable would use actual pointwise weights
    out_dw = F.conv2d(x, w[:K].reshape(K, 1, kH, kW).repeat(1, C//K, 1, 1), 
                      padding=1, groups=min(K, C))
    
    # For true depthwise separable, we'd need separate depthwise weights
    # This is an approximation showing the concept
    return out_dw

# Correct depthwise separable
def method_depthwise_separable():
    """True depthwise separable: separate depth + pointwise."""
    # Check if divisible
    if C % K == 0 or K % C == 0:
        # Depthwise convolution
        groups = min(K, C)
        w_dw = w[:C].reshape(C, 1, kH, kW)
        out = F.conv2d(x, w_dw, padding=1, groups=groups)
        
        # Pointwise (1x1) to expand channels
        w_pw = torch.randn(K, C, 1, 1) if K != C else torch.eye(C).unsqueeze(-1).unsqueeze(-1)
        if K != C:
            out = F.conv2d(out, w_pw)
        return out
    else:
        return F.conv2d(x, w, padding=1)

_ = benchmark(method_depthwise_separable, "Anurupyena depthwise separable", runs=100)
