2020-07-22 19:16:29 +00:00
# pragma once
# include <math.h>
# include "m_fixed.h"
# include "xs_Float.h" // needed for reliably overflowing float->int conversions.
# include "build.h"
2020-07-23 14:45:58 +00:00
// type safe representations of high precision angle and horizon values. Angle uses natural 32 bit overflow to clamp to one rotation.
2020-07-22 19:16:29 +00:00
class binangle
{
unsigned int value ;
2020-07-23 14:40:59 +00:00
inline static constexpr double pi ( ) { return 3.14159265358979323846 ; }
2020-07-22 19:16:29 +00:00
constexpr binangle ( unsigned int v ) : value ( v ) { }
2020-07-23 14:40:59 +00:00
friend constexpr binangle bamang ( unsigned int v ) ;
friend constexpr binangle q16ang ( unsigned int v ) ;
friend constexpr binangle buildang ( unsigned int v ) ;
2020-07-22 19:16:29 +00:00
friend binangle radang ( double v ) ;
friend binangle degang ( double v ) ;
public :
2020-07-23 14:45:58 +00:00
binangle ( ) = default ;
binangle ( const binangle & other ) = default ;
2020-07-22 19:16:29 +00:00
// This class intentionally makes no allowances for implicit type conversions because those would render it ineffective.
constexpr short asbuild ( ) const { return value > > 21 ; }
constexpr fixed_t asq16 ( ) const { return value > > 5 ; }
constexpr double asrad ( ) const { return value * ( pi : : pi ( ) / 0x80000000u ) ; }
constexpr double asdeg ( ) const { return value * ( 90. / 0x40000000 ) ; }
constexpr unsigned asbam ( ) const { return value ; }
double fsin ( ) const { return sin ( asrad ( ) ) ; }
double fcos ( ) const { return cos ( asrad ( ) ) ; }
double ftan ( ) const { return tan ( asrad ( ) ) ; }
2020-07-23 14:40:59 +00:00
int bsin ( ) const { return sintable [ asbuild ( ) ] ; }
int bcos ( ) const { return sintable [ ( asbuild ( ) + 512 ) & 2047 ] ; }
2020-07-22 19:16:29 +00:00
#if 0 // This makes no sense
bool operator < ( binangle other ) const
{
return value < other . value ;
}
bool operator > ( binangle other ) const
{
return value > other . value ;
}
bool operator < = ( binangle other ) const
{
return value < = other . value ;
}
bool operator > = ( binangle other ) const
{
return value > = other . value ;
}
# endif
constexpr bool operator = = ( binangle other ) const
{
return value = = other . value ;
}
constexpr bool operator ! = ( binangle other ) const
{
return value ! = other . value ;
}
2020-07-23 14:40:59 +00:00
constexpr binangle & operator + = ( binangle other )
2020-07-22 19:16:29 +00:00
{
value + = other . value ;
return * this ;
}
2020-07-23 14:40:59 +00:00
constexpr binangle & operator - = ( binangle other )
2020-07-22 19:16:29 +00:00
{
2020-07-23 14:40:59 +00:00
value - = other . value ;
2020-07-22 19:16:29 +00:00
return * this ;
}
constexpr binangle operator + ( binangle other ) const
{
return binangle ( value + other . value ) ;
}
constexpr binangle operator - ( binangle other ) const
{
return binangle ( value - other . value ) ;
}
2020-07-23 15:01:37 +00:00
void interpolate ( binangle a1 , binangle a2 , fix16_t smoothratio )
{
// Calculate in floating point to reduce the error caused by overflows which are to be expected here and then downconvert using a method that is safe to overflow.
// We do not want fixed point multiplications here to trash the result.
double smooth = smoothratio / 65536.f ;
value = xs_CRoundToUInt ( double ( a1 . asbam ( ) ) + smooth * ( double ( a2 . asbam ( ) ) - double ( a1 . asbam ( ) ) ) ) ;
}
2020-07-22 19:16:29 +00:00
2020-07-23 14:45:58 +00:00
} ;
class fixedhoriz
{
2020-07-23 15:08:50 +00:00
int value ;
2020-07-23 14:45:58 +00:00
2020-07-23 15:08:50 +00:00
constexpr fixedhoriz ( int v ) : value ( v ) { }
2020-07-23 14:45:58 +00:00
friend constexpr fixedhoriz q16horiz ( int v ) ;
friend constexpr fixedhoriz buildhoriz ( int v ) ;
public :
fixedhoriz ( ) = default ;
fixedhoriz ( const fixedhoriz & other ) = default ;
// This class intentionally makes no allowances for implicit type conversions because those would render it ineffective.
short asbuild ( ) const { return value > > 16 ; }
constexpr fixed_t asq16 ( ) const { return value ; }
bool operator < ( fixedhoriz other ) const
{
return value < other . value ;
}
bool operator > ( fixedhoriz other ) const
{
return value > other . value ;
}
bool operator < = ( fixedhoriz other ) const
{
return value < = other . value ;
}
bool operator > = ( fixedhoriz other ) const
{
return value > = other . value ;
}
constexpr bool operator = = ( fixedhoriz other ) const
{
return value = = other . value ;
}
constexpr bool operator ! = ( fixedhoriz other ) const
{
return value ! = other . value ;
}
constexpr fixedhoriz & operator + = ( fixedhoriz other )
{
value + = other . value ;
return * this ;
}
constexpr fixedhoriz & operator - = ( fixedhoriz other )
{
value - = other . value ;
return * this ;
}
constexpr fixedhoriz operator - ( ) const
{
return fixedhoriz ( - value ) ;
}
constexpr fixedhoriz operator + ( fixedhoriz other ) const
{
return fixedhoriz ( value + other . value ) ;
}
constexpr fixedhoriz operator - ( fixedhoriz other ) const
{
return fixedhoriz ( value - other . value ) ;
}
2020-07-22 19:16:29 +00:00
} ;
inline constexpr binangle bamang ( unsigned int v ) { return binangle ( v ) ; }
inline constexpr binangle q16ang ( unsigned int v ) { return binangle ( v < < 5 ) ; }
inline constexpr binangle buildang ( unsigned int v ) { return binangle ( v < < 21 ) ; }
2020-07-23 14:40:59 +00:00
inline binangle radang ( double v ) { return binangle ( xs_CRoundToUInt ( v * ( 0x80000000u / binangle : : pi ( ) ) ) ) ; }
inline binangle degang ( double v ) { return binangle ( xs_CRoundToUInt ( v * ( 0x40000000 / 90. ) ) ) ; }
2020-07-22 19:16:29 +00:00
2020-07-23 14:45:58 +00:00
inline constexpr fixedhoriz q16horiz ( int v ) { return fixedhoriz ( v ) ; }
inline constexpr fixedhoriz buildhoriz ( int v ) { return fixedhoriz ( v < < 16 ) ; }