1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2 // Ken Silverman's official web site: "http://www.advsys.net/ken"
3 // See the included license file "BUILDLIC.TXT" for license info.
4 //
5 // This file is based on pragmas.h from Ken Silverman's original Build
6 // source code release and contains routines that were originally
7 // inline assembly but are not now.
8 
9 #ifndef __M_FIXED__
10 #define __M_FIXED__
11 
12 #include <stdlib.h>
13 #include "doomtype.h"
14 
15 #if defined(__GNUC__) && defined(__i386__) && !defined(__clang__)
16 #include "gccinlines.h"
17 #elif defined(_MSC_VER) && defined(_M_IX86)
18 #include "mscinlines.h"
19 #else
20 #include "basicinlines.h"
21 #endif
22 
23 #include "xs_Float.h"
24 
25 #define MAKESAFEDIVSCALE(x) \
26 	inline SDWORD SafeDivScale##x (SDWORD a, SDWORD b) \
27 	{ \
28 		if ((DWORD)abs(a) >> (31-x) >= (DWORD)abs (b)) \
29 			return (a^b)<0 ? FIXED_MIN : FIXED_MAX; \
30 		return DivScale##x (a, b); \
31 	}
32 
33 MAKESAFEDIVSCALE(1)
34 MAKESAFEDIVSCALE(2)
35 MAKESAFEDIVSCALE(3)
36 MAKESAFEDIVSCALE(4)
37 MAKESAFEDIVSCALE(5)
38 MAKESAFEDIVSCALE(6)
39 MAKESAFEDIVSCALE(7)
40 MAKESAFEDIVSCALE(8)
41 MAKESAFEDIVSCALE(9)
42 MAKESAFEDIVSCALE(10)
43 MAKESAFEDIVSCALE(11)
44 MAKESAFEDIVSCALE(12)
45 MAKESAFEDIVSCALE(13)
46 MAKESAFEDIVSCALE(14)
47 MAKESAFEDIVSCALE(15)
48 MAKESAFEDIVSCALE(16)
49 MAKESAFEDIVSCALE(17)
50 MAKESAFEDIVSCALE(18)
51 MAKESAFEDIVSCALE(19)
52 MAKESAFEDIVSCALE(20)
53 MAKESAFEDIVSCALE(21)
54 MAKESAFEDIVSCALE(22)
55 MAKESAFEDIVSCALE(23)
56 MAKESAFEDIVSCALE(24)
57 MAKESAFEDIVSCALE(25)
58 MAKESAFEDIVSCALE(26)
59 MAKESAFEDIVSCALE(27)
60 MAKESAFEDIVSCALE(28)
61 MAKESAFEDIVSCALE(29)
62 MAKESAFEDIVSCALE(30)
63 #undef MAKESAFEDIVSCALE
64 
SafeDivScale31(SDWORD a,SDWORD b)65 inline SDWORD SafeDivScale31 (SDWORD a, SDWORD b)
66 {
67 	if ((DWORD)abs(a) >= (DWORD)abs (b))
68 		return (a^b)<0 ? FIXED_MIN : FIXED_MAX;
69 	return DivScale31 (a, b);
70 }
71 
SafeDivScale32(SDWORD a,SDWORD b)72 inline SDWORD SafeDivScale32 (SDWORD a, SDWORD b)
73 {
74 	if ((DWORD)abs(a) >= (DWORD)abs (b) >> 1)
75 		return (a^b)<0 ? FIXED_MIN : FIXED_MAX;
76 	return DivScale32 (a, b);
77 }
78 
79 #define FixedMul MulScale16
80 #define FixedDiv SafeDivScale16
81 
qinterpolatedown16(SDWORD * out,DWORD count,SDWORD val,SDWORD delta)82 inline void qinterpolatedown16 (SDWORD *out, DWORD count, SDWORD val, SDWORD delta)
83 {
84 	if (count & 1)
85 	{
86 		out[0] = val >> 16;
87 		val += delta;
88 	}
89 	count >>= 1;
90 	while (count-- != 0)
91 	{
92 		int temp = val + delta;
93 		out[0] = val >> 16;
94 		val = temp + delta;
95 		out[1] = temp >> 16;
96 		out += 2;
97 	}
98 }
99 
qinterpolatedown16short(short * out,DWORD count,SDWORD val,SDWORD delta)100 inline void qinterpolatedown16short (short *out, DWORD count, SDWORD val, SDWORD delta)
101 {
102 	if (count)
103 	{
104 		if ((size_t)out & 2)
105 		{ // align to dword boundary
106 			*out++ = (short)(val >> 16);
107 			count--;
108 			val += delta;
109 		}
110 		DWORD *o2 = (DWORD *)out;
111 		DWORD c2 = count>>1;
112 		while (c2-- != 0)
113 		{
114 			SDWORD temp = val + delta;
115 			*o2++ = (temp & 0xffff0000) | ((DWORD)val >> 16);
116 			val = temp + delta;
117 		}
118 		if (count & 1)
119 		{
120 			*(short *)o2 = (short)(val >> 16);
121 		}
122 	}
123 }
124 
125 	//returns num/den, dmval = num%den
DivMod(SDWORD num,SDWORD den,SDWORD * dmval)126 inline SDWORD DivMod (SDWORD num, SDWORD den, SDWORD *dmval)
127 {
128 	*dmval = num % den;
129 	return num / den;
130 }
131 
132 	//returns num%den, dmval = num/den
ModDiv(SDWORD num,SDWORD den,SDWORD * dmval)133 inline SDWORD ModDiv (SDWORD num, SDWORD den, SDWORD *dmval)
134 {
135 	*dmval = num / den;
136 	return num % den;
137 }
138 
139 
140 #define FLOAT2FIXED(f)		xs_Fix<16>::ToFix(f)
141 #define FIXED2FLOAT(f)		((f) / float(65536))
142 #define FIXED2DBL(f)		((f) / double(65536))
143 
144 #endif
145