// Copyright 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

// ospray
#include "rkcommon/math/box.ih"
#include "openvkl/VKLDataType.h"
#include "../common/Data.ih"
// ours
#include "KDTree.ih"
#include "AMRShared.h"

inline vec3f lerp(const box3f box, const vec3f w)
{
  return box.lower + (box.upper-box.lower)*w;
}

inline float max(float a, float b, float c)
{
  return max(max(a,b),c);
}

inline float min(float a, float b, float c)
{
   return min(min(a,b),c);
}

inline float max(float a, float b, float c, float d,
                 float e, float f, float g, float h)
{
  return max(max(max(a,b),max(c,d)),max(max(e,f),max(g,h)));
}

inline float min(float a, float b, float c, float d,
                 float e, float f, float g, float h)
{
  return min(min(min(a,b),min(c,d)),min(min(e,f),min(g,h)));
}

//! "templated" voxel get functions for different data types
#define template_AMR_getVoxel(type)                                              \
/* --------------------------------------------------------------------------\
// versions for pure 32-bit addressing. volume *MUST* be smaller than 2G     \
// ------------------------------------------------------------------------*/\
inline float AMR_getVoxel_##type##_32(const Data1D *uniform data,            \
                                     const varying uint32 index)             \
{                                                                            \
  /* The voxel value at the given index. */                                  \
  return get_##type(*data, index);                                           \
}                                                                            \

template_AMR_getVoxel(uint8);
template_AMR_getVoxel(int16);
template_AMR_getVoxel(uint16);
template_AMR_getVoxel(float);
template_AMR_getVoxel(double);
#undef template_getVoxel

inline float nextafter(const float f, const float s)
{
  const float af = abs(f);
  const float nf = f+s*af*(1.f/(float)(1<<23));
  return nf;
}

inline vec3f nextafter(const vec3f v, const vec3f sign)
{
  return make_vec3f(nextafter(v.x,sign.x),
                    nextafter(v.y,sign.y),
                    nextafter(v.z,sign.z));
}

inline uniform vec3f nextafter(const uniform vec3f v, const uniform float sign)
{
  return make_vec3f(nextafter(v.x,sign),
                    nextafter(v.y,sign),
                    nextafter(v.z,sign));
}
