/* NumRs C API - Auto-generated by cbindgen */

/* Generated with cbindgen:0.26.0 */

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

/**
 * Opaque handle for C
 */
typedef struct NumRsArray NumRsArray;

typedef struct NumRsConv1d NumRsConv1d;

typedef struct NumRsDataset NumRsDataset;

typedef struct NumRsLinear NumRsLinear;

typedef struct NumRsReLU NumRsReLU;

typedef struct NumRsSequential NumRsSequential;

typedef struct NumRsTensor NumRsTensor;

typedef struct NumRsTrainer NumRsTrainer;

typedef struct NumRsTrainerBuilder NumRsTrainerBuilder;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

const int8_t *numrs_version(void);

/**
 * Print startup log
 */
void numrs_print_startup_log(void);

/**
 * Create a new Array from a raw float buffer
 * data: pointer to float array
 * shape: pointer to shape dimensions (uint32_t)
 * ndim: number of dimensions
 */
struct NumRsArray *numrs_array_new(const float *data, const uint32_t *shape,
                                   uintptr_t ndim);

void numrs_array_free(struct NumRsArray *ptr);

void numrs_array_print(const struct NumRsArray *ptr);

struct NumRsTensor *numrs_tensor_new(struct NumRsArray *array,
                                     bool requires_grad);

void numrs_tensor_free(struct NumRsTensor *ptr);

void numrs_tensor_backward(struct NumRsTensor *ptr);

struct NumRsArray *numrs_tensor_data(struct NumRsTensor *ptr);

struct NumRsTensor *numrs_tensor_grad(struct NumRsTensor *ptr);

struct NumRsTensor *numrs_add(struct NumRsTensor *a, struct NumRsTensor *b);

struct NumRsTensor *numrs_sub(struct NumRsTensor *a, struct NumRsTensor *b);

struct NumRsTensor *numrs_mul(struct NumRsTensor *a, struct NumRsTensor *b);

struct NumRsTensor *numrs_div(struct NumRsTensor *a, struct NumRsTensor *b);

struct NumRsTensor *numrs_relu(struct NumRsTensor *a);

struct NumRsTensor *numrs_sigmoid(struct NumRsTensor *a);

struct NumRsTensor *numrs_log(struct NumRsTensor *a);

struct NumRsTensor *numrs_exp(struct NumRsTensor *a);

struct NumRsTensor *numrs_pow(struct NumRsTensor *a, double exponent);

struct NumRsTensor *numrs_matmul(struct NumRsTensor *a, struct NumRsTensor *b);

struct NumRsTensor *numrs_sum(struct NumRsTensor *a, intptr_t _axis);

struct NumRsTensor *numrs_mean(struct NumRsTensor *a, intptr_t _axis);

struct NumRsTensor *numrs_mse_loss(struct NumRsTensor *pred,
                                   struct NumRsTensor *target);

struct NumRsTensor *numrs_softmax(struct NumRsTensor *a, intptr_t axis);

struct NumRsTensor *numrs_reshape(struct NumRsTensor *a,
                                  const uint32_t *shape_ptr, uintptr_t ndim);

struct NumRsTensor *numrs_flatten(struct NumRsTensor *a, uintptr_t start_dim,
                                  uintptr_t end_dim);

struct NumRsSequential *numrs_sequential_new(void);

void numrs_sequential_free(struct NumRsSequential *ptr);

void numrs_sequential_add_linear(struct NumRsSequential *seq,
                                 struct NumRsLinear *layer);

void numrs_sequential_add_relu(struct NumRsSequential *seq,
                               struct NumRsReLU *layer);

struct NumRsTensor *numrs_sequential_forward(struct NumRsSequential *seq,
                                             struct NumRsTensor *input);

struct NumRsLinear *numrs_linear_new(uintptr_t in_features,
                                     uintptr_t out_features);

struct NumRsReLU *numrs_relu_layer_new(void);

struct NumRsConv1d *numrs_conv1d_new(uintptr_t in_channels,
                                     uintptr_t out_channels,
                                     uintptr_t kernel_size, uintptr_t stride,
                                     uintptr_t padding);

struct NumRsDataset *
numrs_dataset_new(const float *inputs, const uint32_t *input_shape,
                  uintptr_t input_ndim, const float *targets,
                  const uint32_t *target_shape, uintptr_t target_ndim,
                  uintptr_t batch_size);

void numrs_dataset_free(struct NumRsDataset *ptr);

struct NumRsTrainerBuilder *
numrs_trainer_builder_new(struct NumRsSequential *model);

struct NumRsTrainerBuilder *
numrs_trainer_builder_learning_rate(struct NumRsTrainerBuilder *builder,
                                    double lr);

struct NumRsTrainer *
numrs_trainer_build_sgd_mse(struct NumRsTrainerBuilder *builder);

void numrs_trainer_fit(struct NumRsTrainer *trainer,
                       struct NumRsDataset *train_data, uintptr_t epochs);

void numrs_trainer_free(struct NumRsTrainer *ptr);

// --- Extended Layers Declarations ---

struct NumRsConv1d *numrs_conv1d_new(uintptr_t in_channels,
                                     uintptr_t out_channels,
                                     uintptr_t kernel_size, uintptr_t stride,
                                     uintptr_t padding);

struct NumRsBatchNorm1d *numrs_batchnorm1d_new(uintptr_t num_features);

struct NumRsDropout *numrs_dropout_new(float p);

struct NumRsFlatten *numrs_flatten_new(uintptr_t start_dim, uintptr_t end_dim);

// Sigmoid/Softmax Layers (distinct from Ops)
struct NumRsSigmoid *numrs_sigmoid_new(void);
struct NumRsSoftmax *numrs_softmax_new(void);

// --- Sequential Adders ---

void numrs_sequential_add_conv1d(struct NumRsSequential *seq,
                                 struct NumRsConv1d *layer);
void numrs_sequential_add_batchnorm1d(struct NumRsSequential *seq,
                                      struct NumRsBatchNorm1d *layer);
void numrs_sequential_add_dropout(struct NumRsSequential *seq,
                                  struct NumRsDropout *layer);
void numrs_sequential_add_flatten(struct NumRsSequential *seq,
                                  struct NumRsFlatten *layer);
void numrs_sequential_add_sigmoid(struct NumRsSequential *seq,
                                  struct NumRsSigmoid *layer);
void numrs_sequential_add_softmax(struct NumRsSequential *seq,
                                  struct NumRsSoftmax *layer);

// --- Extended Optim ---
struct NumRsTrainer *numrs_trainer_build(struct NumRsTrainerBuilder *builder,
                                         const char *optimizer,
                                         const char *loss);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
