// Float simple_mul bytecode loading and input/output processes

#include "iree/base/api.h"
#include "iree/hal/api.h"

// Compiled module embedded here to avoid file IO:
#include "samples/simple_vec_mul/simple_float_mul_bytecode_module_dylib_c.h"

const iree_const_byte_span_t load_bytecode_module_data() {
  const struct iree_file_toc_t *module_file_toc =
      samples_simple_vec_mul_simple_float_mul_bytecode_module_dylib_create();
  return iree_make_const_byte_span(module_file_toc->data,
                                   module_file_toc->size);
}

iree_status_t prepare_input_hal_buffer_views(
    iree_hal_device_t *device, const int buffer_length, void **arg0_buffer,
    void **arg1_buffer, iree_hal_buffer_view_t **arg0_buffer_view,
    iree_hal_buffer_view_t **arg1_buffer_view) {
  iree_status_t result = iree_ok_status();
  *arg0_buffer =
      iree_aligned_alloc(sizeof(uint32_t), sizeof(float) * buffer_length);
  if (*arg0_buffer == NULL) {
    result = iree_make_status(IREE_STATUS_RESOURCE_EXHAUSTED);
  }
  if (iree_status_is_ok(result)) {
    *arg1_buffer =
        iree_aligned_alloc(sizeof(uint32_t), sizeof(float) * buffer_length);
    if (*arg1_buffer == NULL) {
      result = iree_make_status(IREE_STATUS_RESOURCE_EXHAUSTED);
    }
  }

  // Populate initial values
  // arg0 = 0, 1/4, 1/2, 3/4... 1023/4
  // arg1 = 0, 1/2, 1, 3/2... 1023/2
  for (int i = 0; i < buffer_length; ++i) {
    ((float *)*arg0_buffer)[i] = i / 4.0f;
    ((float *)*arg1_buffer)[i] = i / 2.0f;
  }
  // Wrap buffers in shaped buffer views.
  // The buffers can be mapped on the CPU and that can also be used
  // on the device. Not all devices support this, but the ones we have now do.
  iree_hal_dim_t shape[1] = {buffer_length};

  iree_hal_memory_type_t input_memory_type =
      IREE_HAL_MEMORY_TYPE_HOST_LOCAL | IREE_HAL_MEMORY_TYPE_DEVICE_VISIBLE;

  result = iree_hal_buffer_view_wrap_or_clone_heap_buffer(
      iree_hal_device_allocator(device), shape, IREE_ARRAYSIZE(shape),
      IREE_HAL_ELEMENT_TYPE_FLOAT_32, IREE_HAL_ENCODING_TYPE_DENSE_ROW_MAJOR,
      input_memory_type, IREE_HAL_MEMORY_ACCESS_READ, IREE_HAL_BUFFER_USAGE_ALL,
      iree_make_byte_span(*arg0_buffer, sizeof(int32_t) * buffer_length),
      iree_allocator_null(), arg0_buffer_view);

  if (iree_status_is_ok(result)) {
    result = iree_hal_buffer_view_wrap_or_clone_heap_buffer(
        iree_hal_device_allocator(device), shape, IREE_ARRAYSIZE(shape),
        IREE_HAL_ELEMENT_TYPE_FLOAT_32, IREE_HAL_ENCODING_TYPE_DENSE_ROW_MAJOR,
        input_memory_type, IREE_HAL_MEMORY_ACCESS_READ,
        IREE_HAL_BUFFER_USAGE_ALL,
        iree_make_byte_span(*arg1_buffer, sizeof(int32_t) * buffer_length),
        iree_allocator_null(), arg1_buffer_view);
  }
  return result;
}

iree_status_t check_output_data(iree_hal_buffer_mapping_t *mapped_memory) {
  iree_status_t result = iree_ok_status();
  for (int i = 0; i < mapped_memory->contents.data_length / sizeof(float);
       ++i) {
    if (((const float *)mapped_memory->contents.data)[i] != i * i / 8.0f) {
      result = iree_make_status(IREE_STATUS_UNKNOWN, "result mismatches");
      break;
    }
  }
  return result;
}
