#include <stdint.h>  // Para int64_t
#include <stdio.h>
#include <stdlib.h>  // Para malloc e free

/**
 * @brief Calcula o quadrado de números pares em um intervalo e os armazena em um array alocado dinamicamente.
 *
 * Esta função aloca dinamicamente a memória para o array de resultados.
 * O chamador (caller) é responsável por liberar a memória alocada com free()
 * após o uso para evitar vazamentos de memória (memory leak).
 *
 * Otimizações e Boas Práticas:
 * 1. Usa int64_t (de <stdint.h>) para 'number', 'x', e os resultados para lidar com
 * números grandes (até 700.000.000 e seus quadrados).
 * 2. Calcula o tamanho exato necessário para o array antes da alocação.
 * - Apenas números pares são incluídos, o que reduz o tamanho pela metade (aproximadamente).
 * 3. Retorna o array por meio de um ponteiro e usa um ponteiro adicional (result_size)
 * para retornar o tamanho real do array alocado.
 * 4. Verifica a alocação de memória (malloc).
 *
 * @param number O limite superior inclusivo do intervalo (começando em 1).
 * @param result_size Ponteiro para armazenar o tamanho real do array de retorno.
 * @return Um ponteiro para o array int64_t alocado dinamicamente contendo os quadrados,
 * ou NULL em caso de falha na alocação.
 */
int64_t *square(int64_t number, int64_t *result_size) {
    // 1. Otimização: Calcular o tamanho exato do array.
    // O loop itera de 1 a 'number'.
    // A cada 2 números, 1 é par (2, 4, 6...).
    // O número de pares é floor(number / 2).
    int64_t count = number / 2;

    if (count < 0) {  // Garante que o número de elementos não é negativo se 'number' fosse negativo
        count = 0;
    }

    // Armazena o tamanho real do array no ponteiro de saída.
    *result_size = count;

    // Se não houver elementos (count == 0), retorna NULL imediatamente (boa prática)
    if (count == 0) {
        return NULL;
    }

    // 2. Alocação Dinâmica de Memória (Heap).
    // Aloca 'count' elementos do tamanho de int64_t (8 bytes)
    int64_t *list_squared = (int64_t *)malloc(count * sizeof(int64_t));

    // 3. Verificação de Falha na Alocação (Boa Prática).
    if (list_squared == NULL) {
        perror("Falha na alocacao de memoria");  // Imprime uma mensagem de erro
        *result_size = 0;                        // Garante que o tamanho retornado é 0
        return NULL;
    }

    // 4. Preenchimento do Array.
    // Não precisamos de 'if (x % 2 == 0)' dentro do loop, pois sabemos que:
    // O primeiro par é 2. O k-ésimo par é 2 * (k + 1), onde k começa em 0.
    // Simplificando: O par é 2 * (i), onde i começa em 1.

    // O loop interno fará 'count' iterações.
    // 'i' será o índice do array, de 0 a count-1.
    // 'x' será o valor par a ser elevado ao quadrado: 2 * (i + 1).
    for (int64_t i = 0; i < count; i++) {
        int64_t x = 2 * (i + 1);
        list_squared[i] = x * x;
    }

    return list_squared;
}

// Função main (equivalente ao print(square(...)) do Python)
int main() {
    // Usamos um literal long long (sufixo LL) para garantir 64 bits para o valor de entrada
    const int64_t INPUT_NUMBER = 1000000000LL;
    int64_t size = 0;

    // Chama a função e passa o endereço da variável 'size' para receber o tamanho.
    int64_t *result_array = square(INPUT_NUMBER, &size);

    // Verifica se a função retornou um array válido (não NULL).
    if (result_array != NULL) {
        // Exemplo: Imprime apenas o primeiro e o último elemento.
        // O array completo é muito grande para imprimir.
        printf("Chamando square(%lld)\n", INPUT_NUMBER);
        printf("Tamanho do array de retorno: %lld\n", size);

        if (size > 0) {
            printf("Primeiro elemento (quadrado de 2): %lld\n", result_array[0]);

            // O último valor par é 2 * floor(700.000.000 / 2) = 700.000.000
            // O último índice é size - 1
            printf("Ultimo elemento (quadrado de %lld): %lld\n", (size * 2), result_array[size - 1]);
        }

        // 5. Liberação de Memória (Boa Prática de C).
        // É crucial liberar a memória que foi alocada por malloc dentro da função 'square'.
        free(result_array);
        result_array = NULL;  // Boa prática: evitar ponteiros pendentes (dangling pointers)
    } else {
        printf("A funcao square(%lld) retornou um array vazio ou falhou na alocacao de memoria.\n", INPUT_NUMBER);
    }

    return 0;
}