|  | /* | 
|  |  | 
|  | fp_trig.c: floating-point math routines for the Linux-m68k | 
|  | floating point emulator. | 
|  |  | 
|  | Copyright (c) 1998-1999 David Huggins-Daines / Roman Zippel. | 
|  |  | 
|  | I hereby give permission, free of charge, to copy, modify, and | 
|  | redistribute this software, in source or binary form, provided that | 
|  | the above copyright notice and the following disclaimer are included | 
|  | in all such copies. | 
|  |  | 
|  | THIS SOFTWARE IS PROVIDED "AS IS", WITH ABSOLUTELY NO WARRANTY, REAL | 
|  | OR IMPLIED. | 
|  |  | 
|  | */ | 
|  |  | 
|  | #include "fp_emu.h" | 
|  |  | 
|  | static const struct fp_ext fp_one = | 
|  | { | 
|  | .exp = 0x3fff, | 
|  | }; | 
|  |  | 
|  | extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src); | 
|  | extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src); | 
|  | extern struct fp_ext *fp_fmul(struct fp_ext *dest, const struct fp_ext *src); | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_fsqrt(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | struct fp_ext tmp, src2; | 
|  | int i, exp; | 
|  |  | 
|  | dprint(PINSTR, "fsqrt\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | if (IS_ZERO(dest)) | 
|  | return dest; | 
|  |  | 
|  | if (dest->sign) { | 
|  | fp_set_nan(dest); | 
|  | return dest; | 
|  | } | 
|  | if (IS_INF(dest)) | 
|  | return dest; | 
|  |  | 
|  | /* | 
|  | *		 sqrt(m) * 2^(p)	, if e = 2*p | 
|  | * sqrt(m*2^e) = | 
|  | *		 sqrt(2*m) * 2^(p)	, if e = 2*p + 1 | 
|  | * | 
|  | * So we use the last bit of the exponent to decide wether to | 
|  | * use the m or 2*m. | 
|  | * | 
|  | * Since only the fractional part of the mantissa is stored and | 
|  | * the integer part is assumed to be one, we place a 1 or 2 into | 
|  | * the fixed point representation. | 
|  | */ | 
|  | exp = dest->exp; | 
|  | dest->exp = 0x3FFF; | 
|  | if (!(exp & 1))		/* lowest bit of exponent is set */ | 
|  | dest->exp++; | 
|  | fp_copy_ext(&src2, dest); | 
|  |  | 
|  | /* | 
|  | * The taylor row around a for sqrt(x) is: | 
|  | *	sqrt(x) = sqrt(a) + 1/(2*sqrt(a))*(x-a) + R | 
|  | * With a=1 this gives: | 
|  | *	sqrt(x) = 1 + 1/2*(x-1) | 
|  | *		= 1/2*(1+x) | 
|  | */ | 
|  | fp_fadd(dest, &fp_one); | 
|  | dest->exp--;		/* * 1/2 */ | 
|  |  | 
|  | /* | 
|  | * We now apply the newton rule to the function | 
|  | *	f(x) := x^2 - r | 
|  | * which has a null point on x = sqrt(r). | 
|  | * | 
|  | * It gives: | 
|  | *	x' := x - f(x)/f'(x) | 
|  | *	    = x - (x^2 -r)/(2*x) | 
|  | *	    = x - (x - r/x)/2 | 
|  | *          = (2*x - x + r/x)/2 | 
|  | *	    = (x + r/x)/2 | 
|  | */ | 
|  | for (i = 0; i < 9; i++) { | 
|  | fp_copy_ext(&tmp, &src2); | 
|  |  | 
|  | fp_fdiv(&tmp, dest); | 
|  | fp_fadd(dest, &tmp); | 
|  | dest->exp--; | 
|  | } | 
|  |  | 
|  | dest->exp += (exp - 0x3FFF) / 2; | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("fetoxm1\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | if (IS_ZERO(dest)) | 
|  | return dest; | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_fetox(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("fetox\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_ftwotox(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("ftwotox\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_ftentox(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("ftentox\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_flogn(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("flogn\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_flognp1(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("flognp1\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_flog10(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("flog10\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_flog2(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | uprint("flog2\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_fgetexp(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | dprint(PINSTR, "fgetexp\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | if (IS_INF(dest)) { | 
|  | fp_set_nan(dest); | 
|  | return dest; | 
|  | } | 
|  | if (IS_ZERO(dest)) | 
|  | return dest; | 
|  |  | 
|  | fp_conv_long2ext(dest, (int)dest->exp - 0x3FFF); | 
|  |  | 
|  | fp_normalize_ext(dest); | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  | 
|  | struct fp_ext * | 
|  | fp_fgetman(struct fp_ext *dest, struct fp_ext *src) | 
|  | { | 
|  | dprint(PINSTR, "fgetman\n"); | 
|  |  | 
|  | fp_monadic_check(dest, src); | 
|  |  | 
|  | if (IS_ZERO(dest)) | 
|  | return dest; | 
|  |  | 
|  | if (IS_INF(dest)) | 
|  | return dest; | 
|  |  | 
|  | dest->exp = 0x3FFF; | 
|  |  | 
|  | return dest; | 
|  | } | 
|  |  |