simple trigonometric functions as in Sinclair scientific
This commit is contained in:
parent
28243c267d
commit
13d26e7b75
@ -21,7 +21,7 @@ target_link_libraries(decn_cover PUBLIC coverage_config)
|
|||||||
add_executable(decn_test decn_test.c ../utils.c)
|
add_executable(decn_test decn_test.c ../utils.c)
|
||||||
target_link_libraries(decn_test decn_cover coverage_config Catch)
|
target_link_libraries(decn_test decn_cover coverage_config Catch)
|
||||||
|
|
||||||
add_executable(decn_tests catch_main.cpp decn_tests.cpp ../utils.c)
|
add_executable(decn_tests catch_main.cpp decn_tests.cpp decn_tests_trig.cpp ../utils.c)
|
||||||
target_link_libraries(decn_tests decn_cover coverage_config mpfr Catch)
|
target_link_libraries(decn_tests decn_cover coverage_config mpfr Catch)
|
||||||
|
|
||||||
# decn prototyping
|
# decn prototyping
|
||||||
|
@ -84,6 +84,15 @@ const dec80 DECN_LN_10 = {
|
|||||||
0, {23, 2, 58, 50, 92, 99, 40, 45, 68}
|
0, {23, 2, 58, 50, 92, 99, 40, 45, 68}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dec80 DECN_2PI = {
|
||||||
|
0, {62, 83, 18, 53, 7, 17, 95, 86, 48}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 180/pi = 1rad in degree
|
||||||
|
const dec80 DECN_1RAD = {
|
||||||
|
1, {57, 29, 57, 79, 51, 30, 82, 32, 9}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void copy_decn(dec80* const dest, const dec80* const src){
|
void copy_decn(dec80* const dest, const dec80* const src){
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
@ -1254,6 +1263,82 @@ void pow_decn(void) {
|
|||||||
exp_decn();
|
exp_decn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sincos_decn(void) {
|
||||||
|
#define SIN Tmp2Decn
|
||||||
|
#define COS Tmp3Decn
|
||||||
|
#define STP Tmp4Decn
|
||||||
|
|
||||||
|
remove_leading_zeros(&AccDecn);
|
||||||
|
|
||||||
|
// TODO: implement scaling to 0..2pi
|
||||||
|
copy_decn(&BDecn, &DECN_2PI);
|
||||||
|
if (compare_magn() == 1) {
|
||||||
|
set_dec80_NaN(&AccDecn);
|
||||||
|
set_dec80_NaN(&BDecn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_dec80_zero(&BDecn);
|
||||||
|
if (compare_magn() == -1) {
|
||||||
|
set_dec80_NaN(&AccDecn);
|
||||||
|
set_dec80_NaN(&BDecn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_decn(&STP, &AccDecn);
|
||||||
|
copy_decn(&COS, &DECN_1);
|
||||||
|
set_dec80_zero(&SIN);
|
||||||
|
// 0.0 00 05
|
||||||
|
SIN.lsu[2] = 5;
|
||||||
|
negate_decn(&SIN);
|
||||||
|
while (STP.exponent >= 0) {
|
||||||
|
// COS = COS - SIN / 10000
|
||||||
|
copy_decn(&AccDecn, &COS);
|
||||||
|
copy_decn(&BDecn, &SIN);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
negate_decn(&BDecn);
|
||||||
|
add_decn();
|
||||||
|
copy_decn(&COS, &AccDecn);
|
||||||
|
// SIN = SIN + COS / 10000
|
||||||
|
copy_decn(&AccDecn, &SIN);
|
||||||
|
copy_decn(&BDecn, &COS);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
shift_right(&BDecn);
|
||||||
|
add_decn();
|
||||||
|
copy_decn(&SIN, &AccDecn);
|
||||||
|
// STP = STP - 0.0 00 1
|
||||||
|
copy_decn(&AccDecn, &STP);
|
||||||
|
set_dec80_zero(&BDecn);
|
||||||
|
BDecn.lsu[2] = 10;
|
||||||
|
negate_decn(&BDecn);
|
||||||
|
add_decn();
|
||||||
|
copy_decn(&STP, &AccDecn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sin_decn(void) {
|
||||||
|
sincos_decn();
|
||||||
|
copy_decn(&AccDecn, &SIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cos_decn(void) {
|
||||||
|
sincos_decn();
|
||||||
|
copy_decn(&AccDecn, &COS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tan_decn(void) {
|
||||||
|
sincos_decn();
|
||||||
|
copy_decn(&AccDecn, &SIN);
|
||||||
|
copy_decn(&BDecn, &COS);
|
||||||
|
div_decn();
|
||||||
|
}
|
||||||
|
#undef SIN
|
||||||
|
#undef COS
|
||||||
|
|
||||||
|
|
||||||
static void set_str_error(void){
|
static void set_str_error(void){
|
||||||
Buf[0] = 'E';
|
Buf[0] = 'E';
|
||||||
|
@ -86,6 +86,10 @@ void exp_decn(void);
|
|||||||
void exp10_decn(void);
|
void exp10_decn(void);
|
||||||
void pow_decn(void);
|
void pow_decn(void);
|
||||||
|
|
||||||
|
void sin_decn(void);
|
||||||
|
void cos_decn(void);
|
||||||
|
void tan_decn(void);
|
||||||
|
|
||||||
//Buf should hold at least 18 + 4 + 5 + 1 = 28
|
//Buf should hold at least 18 + 4 + 5 + 1 = 28
|
||||||
#define DECN_BUF_SIZE 28
|
#define DECN_BUF_SIZE 28
|
||||||
extern __xdata char Buf[DECN_BUF_SIZE];
|
extern __xdata char Buf[DECN_BUF_SIZE];
|
||||||
|
138
src/decn/decn_tests_trig.cpp
Normal file
138
src/decn/decn_tests_trig.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <boost/multiprecision/mpfr.hpp>
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include "decn.h"
|
||||||
|
namespace bmp = boost::multiprecision;
|
||||||
|
using Catch::Matchers::Equals;
|
||||||
|
|
||||||
|
static void sin_test(
|
||||||
|
const char* a_str, int a_exp, double rtol=5e-3, double atol=1e-3)
|
||||||
|
{
|
||||||
|
CAPTURE(a_str); CAPTURE(a_exp);
|
||||||
|
build_dec80(a_str, a_exp);
|
||||||
|
sin_decn();
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CAPTURE(Buf); // acc / b
|
||||||
|
|
||||||
|
bmp::mpfr_float::default_precision(50);
|
||||||
|
std::string a_full_str(a_str);
|
||||||
|
a_full_str += "e" + std::to_string(a_exp);
|
||||||
|
|
||||||
|
bmp::mpfr_float a_actual(a_full_str);
|
||||||
|
a_actual = sin(a_actual);
|
||||||
|
CAPTURE(a_actual); // acc / b
|
||||||
|
|
||||||
|
bmp::mpfr_float calculated(Buf);
|
||||||
|
if (rtol >= 0) {
|
||||||
|
bmp::mpfr_float rel_diff = abs((a_actual - calculated) / a_actual);
|
||||||
|
CHECK(rel_diff < rtol);
|
||||||
|
} else {
|
||||||
|
bmp::mpfr_float diff = abs(a_actual - calculated);
|
||||||
|
CHECK(diff < atol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cos_test(
|
||||||
|
const char* a_str, int a_exp, double rtol=1e-2)
|
||||||
|
{
|
||||||
|
CAPTURE(a_str); CAPTURE(a_exp);
|
||||||
|
build_dec80(a_str, a_exp);
|
||||||
|
cos_decn();
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CAPTURE(Buf); // acc / b
|
||||||
|
|
||||||
|
bmp::mpfr_float::default_precision(50);
|
||||||
|
std::string a_full_str(a_str);
|
||||||
|
a_full_str += "e" + std::to_string(a_exp);
|
||||||
|
|
||||||
|
bmp::mpfr_float a_actual(a_full_str);
|
||||||
|
a_actual = cos(a_actual);
|
||||||
|
CAPTURE(a_actual); // acc / b
|
||||||
|
|
||||||
|
bmp::mpfr_float calculated(Buf);
|
||||||
|
bmp::mpfr_float rel_diff = abs((a_actual - calculated) / a_actual);
|
||||||
|
|
||||||
|
CHECK(rel_diff < rtol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tan_test(
|
||||||
|
const char* a_str, int a_exp, double rtol=1e-2)
|
||||||
|
{
|
||||||
|
CAPTURE(a_str); CAPTURE(a_exp);
|
||||||
|
build_dec80(a_str, a_exp);
|
||||||
|
tan_decn();
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CAPTURE(Buf); // acc / b
|
||||||
|
|
||||||
|
bmp::mpfr_float::default_precision(50);
|
||||||
|
std::string a_full_str(a_str);
|
||||||
|
a_full_str += "e" + std::to_string(a_exp);
|
||||||
|
|
||||||
|
bmp::mpfr_float a_actual(a_full_str);
|
||||||
|
a_actual = tan(a_actual);
|
||||||
|
CAPTURE(a_actual); // acc / b
|
||||||
|
|
||||||
|
bmp::mpfr_float calculated(Buf);
|
||||||
|
bmp::mpfr_float rel_diff = abs((a_actual - calculated) / a_actual);
|
||||||
|
|
||||||
|
CHECK(rel_diff < rtol);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("sin") {
|
||||||
|
sin_test("0.1", 0);
|
||||||
|
sin_test("0.05", 0);
|
||||||
|
sin_test("0.01", 0, -1);
|
||||||
|
sin_test("0.001", 0, -1);
|
||||||
|
sin_test("0.0001", 0, -1);
|
||||||
|
sin_test("0.00001", 0, -1);
|
||||||
|
sin_test("0.000001", 0, -1);
|
||||||
|
sin_test("0.0", 0, -1);
|
||||||
|
sin_test("0.2", 0);
|
||||||
|
sin_test("0.3", 0);
|
||||||
|
sin_test("0.4", 0);
|
||||||
|
sin_test("0.9", 0);
|
||||||
|
sin_test("1.5", 0);
|
||||||
|
sin_test("2.0", 0);
|
||||||
|
sin_test("2.5", 0);
|
||||||
|
sin_test("3.0", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("cos") {
|
||||||
|
cos_test("0.1", 0);
|
||||||
|
cos_test("0.05", 0);
|
||||||
|
cos_test("0.01", 0);
|
||||||
|
cos_test("0.001", 0);
|
||||||
|
cos_test("0.0001", 0);
|
||||||
|
cos_test("0.00001", 0);
|
||||||
|
cos_test("0.000001", 0);
|
||||||
|
cos_test("0.0", 0);
|
||||||
|
cos_test("0.2", 0);
|
||||||
|
cos_test("0.3", 0);
|
||||||
|
cos_test("0.4", 0);
|
||||||
|
cos_test("0.9", 0);
|
||||||
|
cos_test("1.5", 0);
|
||||||
|
cos_test("2.0", 0);
|
||||||
|
cos_test("2.5", 0);
|
||||||
|
cos_test("3.0", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("tan") {
|
||||||
|
tan_test("0.1", 0);
|
||||||
|
tan_test("0.05", 0);
|
||||||
|
tan_test("0.01", 0);
|
||||||
|
tan_test("0.001", 0);
|
||||||
|
tan_test("0.0001", 0);
|
||||||
|
tan_test("0.00001", 0);
|
||||||
|
tan_test("0.000001", 0, -1);
|
||||||
|
tan_test("0.0", 0, -1);
|
||||||
|
tan_test("0.2", 0);
|
||||||
|
tan_test("0.3", 0);
|
||||||
|
tan_test("0.4", 0);
|
||||||
|
tan_test("0.9", 0);
|
||||||
|
tan_test("1.5", 0);
|
||||||
|
tan_test("2.0", 0);
|
||||||
|
tan_test("2.5", 0);
|
||||||
|
tan_test("3.0", 0);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user