%%cu
#include <cuda_runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <libgen.h>
#include <unistd.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <time.h>

#define FILE_NAME "/content/datSeq1M.bin"
#define NUM_ITERATIONS 10
#define SEQ_LENGTH 1024
#define NUM_SEQUENCES (1 << (NUM_ITERATIONS))
#define BLOCK_SIZE 256

__global__ void bitonic_sort_step(int *values, const int stage, const int step) {
  unsigned int tId = threadIdx.x;
  unsigned int pId = tId + blockIdx.x * blockDim.x;

  unsigned int partner = pId ^ step;

  if (pId < partner) {
    if ((tId & stage) == 0) {
      if (values[pId] > values[partner]) {
        int tmp = values[pId];
        values[pId] = values[partner];
        values[partner] = tmp;
      }
    } else {
      if (values[pId] < values[partner]) {
        int tmp = values[pId];
        values[pId] = values[partner];
        values[partner] = tmp;
      }
    }
  }
}

__global__ void bitonic_merge(int *values, int stage, int step) {
  int length = 1 << (stage + 1);
  int index = threadIdx.x + blockIdx.x * blockDim.x;
  int base = (index / length) * length;
  int partner = base + length / 2 + (index % (length / 2));

  if (index < partner) {
    if ((index & (length / 2)) == 0) {
      if (values[index] > values[partner]) {
        int tmp = values[index];
        values[index] = values[partner];
        values[partner] = tmp;
      }
    } else {
      if (values[index] < values[partner]) {
        int tmp = values[index];
        values[index] = values[partner];
        values[partner] = tmp;
      }
    }
  }
}

void bitonic_sort(int *values, int sequence_length) {
  for (int stage = 0; stage < (int)log2f(sequence_length); ++stage) {
    for (int step = sequence_length / 2; step > 0; step /= 2) {
      unsigned int numBlocks = (sequence_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
      bitonic_sort_step<<<numBlocks, BLOCK_SIZE>>>(values, stage, step);
      cudaDeviceSynchronize();
    }
  }
}

void read_sequence(int *data) {
  FILE *fp = fopen(FILE_NAME, "rb");
  fseek(fp, sizeof(int), SEEK_SET); // Skip the first integer
  if (fp == NULL) {
    fprintf(stderr, "Failed to open the input file\n");
    exit(1);
  }
  for (int i = 0; i < NUM_SEQUENCES * SEQ_LENGTH; i++) {
    if (fread(&data[i], sizeof(int), 1, fp) != 1) {
      fprintf(stderr, "Failed to read the input file\n");
      exit(1);
    }
  }
  fclose(fp);
}

bool isSorted(int* data, int size) {
  for (int i = 0; i < size - 1; i++) {
    if (data[i] > data[i + 1])
      return false;
  }
  return true;
}

int main() {
  int *data = (int *)malloc(NUM_SEQUENCES * SEQ_LENGTH * sizeof(int));
  int *d_data;


  // Read sequences from the file
  read_sequence(data);

  // Allocate memory on GPU
  cudaMalloc((void **)&d_data, NUM_SEQUENCES * SEQ_LENGTH * sizeof(int));
  cudaMemcpy(d_data, data, NUM_SEQUENCES * SEQ_LENGTH * sizeof(int), cudaMemcpyHostToDevice);

  // Perform sorting iterations
  for (int i = 0; i < NUM_ITERATIONS; ++i) {
    int seq_length = SEQ_LENGTH << i;
    printf("Iteration %d: Sorting %d sequences of length %d\n", i + 1, NUM_SEQUENCES >> i, seq_length);
    bitonic_sort(d_data, seq_length);
  }

  cudaMemcpy(data, d_data, NUM_SEQUENCES * SEQ_LENGTH * sizeof(int), cudaMemcpyDeviceToHost);
  cudaFree(d_data);

  // Write output to a file
  FILE *fp = fopen("sorted_output.bin", "wb");
  fwrite(data, sizeof(int), SEQ_LENGTH * NUM_SEQUENCES, fp);
  fclose(fp);

  // Print the sorted data
  for (int i = 0; i < 20; i++) {
    printf("%d ", data[i]);
    if( i == 10 ) break;
  }

  // Check if the array is sorted
  bool isOrdered = isSorted(data, NUM_SEQUENCES * SEQ_LENGTH);

  // Print the result of the ordering check
  if (isOrdered) {
    printf("The array is ordered.\n");
  } else {
    printf("The array is not ordered.\n");
  }

  free(data);
  return 0;
}

This isnt ordering the input file