/*
 * Voxel-a-tord
 * fpmath.h: fixed point math implementation.
 * Copyright (c) 2022 986-Studio. All rights reserved.
 *
 * Created by Manoël Trapier on 29/09/2022..
 */
#include <stdint.h>
#include <math.h>

#ifndef VOXELATOR_FPMATH_H
#define VOXELATOR_FPMATH_H

/* Enable to debug code without having the fix point implementation interfering */
//#define USE_FLOATING_POINT

#ifndef USE_FLOATING_POINT
/*** Setting for the Fixed Point numbers. ***/
typedef int32_t fp_num_t; /**< The base type used for the FP number */
/* These defines should not be used outside of this header file */
#define FP_DECIMAL_BITS (16) /**< Number of bit used for the decimal part */
#define FP_DIVISOR (1 << FP_DECIMAL_BITS)

#define FP_GET_INT(_fp) ((_fp) / FP_DIVISOR)
#define FP_SET_INT(_val) (fp_num_t)((_val) * FP_DIVISOR)

#define FP_GET_FRAC(_val) (fp_num_t)(_val - FP_GET_INT(_val))
#define FP_SET_FLT(_val) (fp_num_t)(floor((_val) * FP_DIVISOR))

#define FP_MUL(_a, _b) (fp_num_t)(((int64_t)(_a) * (int64_t)(_b)) / FP_DIVISOR)
#define FP_DIV(_a, _b) (fp_num_t)(((int64_t)(_a) * FP_DIVISOR) / (_b))

#define fpsin(_val) (fp_num_t)(sin((_val) / 180 * M_PI) * FP_DIVISOR)
#define fpcos(_val) (fp_num_t)(cos((_val) / 180 * M_PI) * FP_DIVISOR)

#else
typedef double fp_num_t;

#define FP_GET_INT(_fp) ( floor(_fp) )
#define FP_SET_INT(_val) (fp_num_t)(_val)
#define FP_GET_FRAC(_val) (fp_num_t)(_val - FP_GET_INT(_val))
#define FP_SET_FLT(_val) (fp_num_t)(_val)

#define FP_MUL(_a, _b) ((_a) * (_b))
#define FP_DIV(_a, _b) ((_a) / (_b))

#define fpsin(_val) sin((_val) / 180 * M_PI)
#define fpcos(_val) cos((_val) / 180 * M_PI)

#endif

#endif /* VOXELATOR_FPMATH_H */
