You are an CUDA helper! Please help me remaking this code in c to work with CUDA:

#include <cuda.h>
#include <stdio.h>

#define BLOCK_SIZE 32
#define STRASSEN_THRESHOLD 64

__global__ void padMatrix(float *A, float *paddedA, int N)
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row < N && col < N)
    {
        paddedA[row * (2 * N) + col] = A[row * N + col];
    }
}

__global__ void padIdentity(float *I, float *paddedI, int N)
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row == col && row < N)
    {
        paddedI[row * (2 * N) + col] = 1.0f;
    }
    else if (row < N && col < N)
    {
        paddedI[row * (2 * N) + col] = 0.0f;
    }
}

__global__ void splitMatrix(float *A, float *B, float *C, float *D, float *E, float *F, float *G, float *H, int N)
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row < N / 2 && col < N / 2)
    {
        C[row * (N / 2) + col] = A[row * N + col];
        D[row * (N / 2) + col] = A[row * N + col + N / 2];
        E[row * (N / 2) + col] = B[row * N + col];
        F[row * (N / 2) + col] = B[row * N + col + N / 2];
    }
    else if (row < N / 2 && col >= N / 2)
    {
        D[row * (N / 2) + (col - N / 2)] = A[row * N + col];
        F[row * (N / 2) + (col - N / 2)] = B[row * N + col];
    }
    else if (row >= N / 2 && col < N / 2)
    {
        G[(row - N / 2) * (N / 2) + col] = A[row * N + col];
        H[(row - N / 2) * (N / 2) + col] = B[row * N + col];
    }
    else
    {
        H[(row - N / 2) * (N / 2) + (col - N / 2)] = A[row * N + col];
    }
}

__global__ void mergeMatrix(float *A, float *B, float *C, float *D, float *E, float *F, float *G, float *H, int N)
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row < N && col < N)
    {
        A[row * N + col] = A[row * N + col] + B[row * N + col] + D[row * N + col] - F[row * N + col];
        C[row * N + col] = A[row * N + col] + D[row * N + col];
        E[row * N + col] = A[row * N + col] - B[row * N + col] + F[row * N + col];
        H[row * N + col] = G[row * N + col] + H[row * N + col];
        B[row * N + col] = A[row * N + col] + B[row * N + col];
        D[row * N + col] = G[row * N + col] - H[row * N + col];
        F[row * N + col] = A[row * N + col] - D[row * N + col];
        G[row * N + col] = B[row * N + col] - F[row * N + col];
    }
}

__global__ void strassenStep(float *A, float *B, float *C, int N)
{
    if (N <= STRASSEN_THRESHOLD)
    {
        // Perform standard matrix multiplication for small matrices
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                float sum = 0.0f;
                for (int k = 0; k < N; k++)
                {
                    sum += A[i * N + k] * B[k * N + j];
                }
                C[i * N + j] = sum;
            }
        }
    }
    else
    {
        // Split matrices into quarters and pad them
        int halfN = N / 2;
        float *paddedA = new float[N * N * 4];
        float *paddedB = new float[N * N * 4];
        float *paddedC = new float[N * N * 4];
        float *paddedD = new float[N * N * 4];
        float *paddedE = new float[N * N * 4];
        float *paddedF = new float[N * N * 4];
        float *paddedG = new float[N * N * 4];
        float *paddedH = new float[N * N * 4];

        padMatrix<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(A, paddedA, N);
        padMatrix<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(B, paddedB, N);

        // Calculate P1, P2, P3, P4, P5, P6, P7
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 0 * N * halfN, paddedB + 0 * N * halfN, paddedC, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 0 * N * halfN, paddedB + 1 * N * halfN, paddedD, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 1 * N * halfN, paddedB + 0 * N * halfN, paddedE, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 1 * N * halfN, paddedB + 1 * N * halfN, paddedF, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 0 * N * halfN + halfN, paddedC + 0 * N * halfN + halfN, paddedG, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedE + 0 * N * halfN + halfN, paddedF + 1 * N * halfN + halfN, paddedH, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 0 * N * halfN + halfN, paddedB + 0 * N * halfN, paddedG + 0 * N * halfN, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 0 * N * halfN + halfN, paddedB + 1 * N * halfN + halfN, paddedH + 0 * N * halfN, halfN);
        strassenStep<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA + 1 * N * halfN, paddedB + 0 * N * halfN + halfN, paddedH + 1 * N * halfN, halfN);

        // Merge results to get C
        mergeMatrix<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA, paddedE, paddedC, paddedG, paddedC, paddedH, paddedC, paddedD, halfN);
        mergeMatrix<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedA, paddedF, paddedC, paddedH, paddedC, paddedG, paddedC, paddedE, halfN);
        mergeMatrix<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedD, paddedF, paddedC, paddedH, paddedC, paddedG, paddedC, paddedA, halfN);
        mergeMatrix<<<(N / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(paddedD, paddedE, paddedC, paddedG, paddedC, paddedH, paddedC, paddedF, halfN);

        // Copy result back to device memory
        for (int i = 0; i < N * N; i++)
        {
            C[i] = paddedC[i];
        }

        delete[] paddedA;
        delete[] paddedB;
        delete[] paddedC;
        delete[] paddedD;
        delete[] paddedE;
        delete[] paddedF;
        delete[] paddedG;
        delete[] paddedH;
    }
}

void multiplyMatrices(float *A, float *B, float *C, int N)
{
    int Np = N;
    while (Np % 2 == 0)
    {
        Np *= 2;
    }
    // Allocate host memory for padded matrices
    float *hostPaddedA = new float[Np * Np];
    float *hostPaddedB = new float[Np * Np];
    memset(hostPaddedA, 0, Np * Np * sizeof(float));
    memset(hostPaddedB, 0, Np * Np * sizeof(float));
    // Pad matrices
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            hostPaddedA[i * Np + j] = A[i * N + j];
            hostPaddedB[i * Np + j] = B[i * N + j];
        }
    }
    // Allocate device memory
    float *d_A, *d_B, *d_C, *d_paddedA, *d_paddedB;
    cudaMalloc(&d_A, Np * Np * sizeof(float));
    cudaMalloc(&d_B, Np * Np * sizeof(float));
    cudaMalloc(&d_C, Np * Np * sizeof(float));
    cudaMalloc(&d_paddedA, Np * Np * sizeof(float));
    cudaMalloc(&d_paddedB, Np * Np * sizeof(float));
    // Copy padded matrices to device
    cudaMemcpy(d_paddedA, hostPaddedA, Np * Np * sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpy(d_paddedB, hostPaddedB, Np * Np * sizeof(float), cudaMemcpyHostToDevice);
    // Set up identity matrix on the host
    float *hostIdentity = new float[N * N];
    memset(hostIdentity, 0, N * N * sizeof(float));
    for (int i = 0; i < N; i++)
    {
        hostIdentity[i * N + i] = 1.0f;
    }
    // Pad identity matrix
    float *hostPaddedIdentity = new float[Np * Np];
    memset(hostPaddedIdentity, 0, Np * Np * sizeof(float));
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            hostPaddedIdentity[i * Np + j] = hostIdentity[i * N + j];
        }
    }
    // Allocate device memory for padded identity
    float *d_paddedIdentity;
    cudaMalloc(&d_paddedIdentity, Np * Np * sizeof(float));
    // Copy padded identity to device
    cudaMemcpy(d_paddedIdentity, hostPaddedIdentity, Np * Np * sizeof(float), cudaMemcpyHostToDevice);
    // Call kernel to perform Strassen's algorithm
    strassenStep<<<(Np / 2) / BLOCK_SIZE, BLOCK_SIZE>>>(d_paddedA, d_paddedB, d_C, Np);
    // Copy result back to host
    cudaMemcpy(C, d_C, N * N * sizeof(float), cudaMemcpyDeviceToHost);
    // Free device memory
    cudaFree(d_A);
    cudaFree(d_B);
    cudaFree(d_C);
    cudaFree(d_paddedA);
    cudaFree(d_paddedB);
    cudaFree(d_paddedIdentity);
    // Free host memory
    delete[] hostPaddedA;
    delete[] hostPaddedB;
    delete[] hostIdentity;
    delete[] hostPaddedIdentity;
    // Check for errors
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess)
    {
        printf("CUDA error: %s\n", cudaGetErrorString(err));
        exit(-1);
    }
}

int main()
{
    int N = 128; // Change this to your desired matrix size
    float *hostA = new float[N * N];
    float *hostB = new float[N * N];
    float *hostC = new float[N * N];
    // Initialize matrices A and B with random values (or your own data)
    srand(time(NULL));
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            hostA[i * N + j] = rand() / (float)(RAND_MAX);
            hostB[i * N + j] = rand() / (float)(RAND_MAX);
        }
    }
    // Call the function to multiply the matrices
    multiplyMatrices(hostA, hostB, hostC, N);
    // Print the result matrix (optional)
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            printf("%.2f ", hostC[i * N + j]);
        }
        printf("\n");
    }
    // Free host memory
    delete[] hostA;
    delete[] hostB;
    delete[] hostC;
    return 0;
}