implemented arctan
This commit is contained in:
		| @ -1297,19 +1297,39 @@ void project_decn_into_0_2pi(void) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // K. Shirriff, "Reversing Sinclair's amazing 1974 calculator hack - half the ROM of the HP-35" | ||||
| // http://files.righto.com/calculator/sinclair_scientific_simulator.html | ||||
| #define SIN Tmp2Decn | ||||
| #define COS Tmp3Decn | ||||
| #define THETA Tmp4Decn | ||||
| void sincos_decn(void) { | ||||
| void sincos_decn(const uint8_t sincos_arctan) { | ||||
| 	const uint8_t is_negative = AccDecn.exponent < 0; | ||||
| 	if (sincos_arctan) { | ||||
| 		set_dec80_zero(&THETA); | ||||
| 		if (is_negative) negate_decn(&AccDecn); | ||||
| 		copy_decn(&COS, &AccDecn); | ||||
| 		copy_decn(&SIN, &DECN_1); | ||||
| 	} else { | ||||
| 		project_decn_into_0_2pi(); | ||||
|  | ||||
| 		copy_decn(&THETA, &AccDecn); | ||||
| 		copy_decn(&COS, &DECN_1); | ||||
| 		set_dec80_zero(&SIN); | ||||
| 		// 0.0 00 05 | ||||
| 		SIN.lsu[2] = 5; | ||||
| 		negate_decn(&SIN); | ||||
| 	while (THETA.exponent >= 0) { | ||||
| 	} | ||||
| 	do { | ||||
| 		if (sincos_arctan) { | ||||
| 			// THETA is in AccDecn from previous iteration | ||||
| 			if (COS.exponent < 0) { | ||||
| 				if (is_negative) negate_decn(&AccDecn); | ||||
| 				break; | ||||
| 			} | ||||
| 		} else { | ||||
| 			if (THETA.exponent < 0) { | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		// COS = COS - SIN / 10000 | ||||
| 		copy_decn(&AccDecn, &COS); | ||||
| 		copy_decn(&BDecn, &SIN); | ||||
| @ -1329,32 +1349,36 @@ void sincos_decn(void) { | ||||
| 		shift_right(&BDecn); | ||||
| 		add_decn(); | ||||
| 		copy_decn(&SIN, &AccDecn); | ||||
| 		// THETA = THETA - 0.0 00 1 | ||||
| 		// THETA = THETA -/+ 0.0 00 1 | ||||
| 		copy_decn(&AccDecn, &THETA); | ||||
| 		set_dec80_zero(&BDecn); | ||||
| 		BDecn.lsu[2] = 10; | ||||
| 		negate_decn(&BDecn); | ||||
| 		if (!sincos_arctan) negate_decn(&BDecn); | ||||
| 		add_decn(); | ||||
| 		copy_decn(&THETA, &AccDecn); | ||||
| 	} | ||||
| 	} while (1); | ||||
| } | ||||
|  | ||||
| void sin_decn(void) { | ||||
| 	sincos_decn(); | ||||
| 	sincos_decn(0); | ||||
| 	copy_decn(&AccDecn, &SIN); | ||||
| } | ||||
|  | ||||
| void cos_decn(void) { | ||||
| 	sincos_decn(); | ||||
| 	sincos_decn(0); | ||||
| 	copy_decn(&AccDecn, &COS); | ||||
| } | ||||
|  | ||||
| void tan_decn(void) { | ||||
| 	sincos_decn(); | ||||
| 	sincos_decn(0); | ||||
| 	copy_decn(&AccDecn, &SIN); | ||||
| 	copy_decn(&BDecn, &COS); | ||||
| 	div_decn(); | ||||
| } | ||||
|  | ||||
| void arctan_decn(void) { | ||||
| 	sincos_decn(1); | ||||
| } | ||||
| #undef SIN | ||||
| #undef COS | ||||
| #undef THETA | ||||
|  | ||||
| @ -86,10 +86,10 @@ void exp_decn(void); | ||||
| void exp10_decn(void); | ||||
| void pow_decn(void); | ||||
|  | ||||
| void project_decn_into_0_2pi(void); | ||||
| void sin_decn(void); | ||||
| void cos_decn(void); | ||||
| void tan_decn(void); | ||||
| void arctan_decn(void); | ||||
| void to_degree_decn(void); | ||||
| void to_radian_decn(void); | ||||
|  | ||||
| @ -110,6 +110,13 @@ void decn_to_str_complete(const dec80* x); | ||||
| void build_decn_at(dec80* dest, const char* signif_str, exp_t exponent); | ||||
| #endif | ||||
|  | ||||
| #define PRINT_DEC80(n, v) \ | ||||
| 	printf(n " %d %5d: ", v.exponent < 0, get_exponent(&v)); \ | ||||
| 	for (int i = 0; i < DEC80_NUM_LSU; i++) { \ | ||||
| 		printf("%02d ", v.lsu[i]); \ | ||||
| 	} \ | ||||
| 	fputc('\n', stdout); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -53,6 +53,12 @@ static void tan_test( | ||||
| 	trig_test(tan_decn, [](bmp::mpfr_float x) -> bmp::mpfr_float {return tan(x);}, a_str, a_exp, rtol, atol); | ||||
| } | ||||
|  | ||||
| static void atan_test( | ||||
| 	const char* a_str, int a_exp, double rtol=5e-3, double atol=1e-3) | ||||
| { | ||||
| 	trig_test(arctan_decn, [](bmp::mpfr_float x) -> bmp::mpfr_float {return atan(x);}, a_str, a_exp, rtol, atol); | ||||
| } | ||||
|  | ||||
|  | ||||
| const char * const pi = "3.141592653589793239"; | ||||
| const char * const pi_threequarters = "2.356194490192344929"; | ||||
| @ -145,3 +151,19 @@ TEST_CASE("tan") { | ||||
| 	tan_test("2.5", 0); | ||||
| 	tan_test("3.0", 0); | ||||
| } | ||||
|  | ||||
| TEST_CASE("arctan") { | ||||
| 	atan_test("0.001", 0); | ||||
| 	atan_test("-0.001", 0); | ||||
| 	atan_test("0.7", 0); | ||||
| 	atan_test("-0.7", 0); | ||||
| 	atan_test("0.1", 0); | ||||
| 	atan_test("-0.1", 0); | ||||
| 	atan_test("1.0", 0); | ||||
| 	atan_test("-1.0", 0); | ||||
| 	atan_test("2.0", 0); | ||||
| 	atan_test("-2.0", 0); | ||||
| 	atan_test("3.0", 0); | ||||
| 	atan_test("-3.0", 0); | ||||
| 	atan_test("0", 0, -1); | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user