@@ -7,6 +7,17 @@ SUITE( fbc_tests.optimizations.inline_ops )
77 const EPSILON_SNG as single = 1.19290929e-7
88 const EPSILON_DBL as double = 2.2204460492503131e-016
99
10+ '' fast floating point is NOT precise
11+ # if __FB_FPMODE__ = "fast"
12+ '' good to about 3 decimal places for
13+ '' cos/sin on -gen gas -fpu sse -fpmode fast
14+ const EPSILON_SNG_FPU as single = EPSILON_SNG * 2000
15+ const EPSILON_DBL_FPU as double = EPSILON_DBL * 2000
16+ # else
17+ const EPSILON_SNG_FPU as single = EPSILON_SNG
18+ const EPSILON_DBL_FPU as double = EPSILON_DBL
19+ # endif
20+
1021 #define hFixF( x ) (floorf( abs( x ) ) * sgn( x ))
1122 #define hFixD( x ) ( floor( abs( x ) ) * sgn( x ))
1223
@@ -30,7 +41,7 @@ SUITE( fbc_tests.optimizations.inline_ops )
3041 end if
3142 end function
3243
33- TEST( all )
44+ TEST( sgn_ )
3445
3546 scope
3647 dim as long l
@@ -58,6 +69,10 @@ SUITE( fbc_tests.optimizations.inline_ops )
5869 ll = &h8000000000000000l l : CU_ASSERT_EQUAL( sgn( ll ), - 1 )
5970 end scope
6071
72+ END_TEST
73+
74+ TEST( abs_ )
75+
6176 '' Not all the abs() tests below are useful to test abs(), but they
6277 '' also help testing -gen gcc's number literal emitting.
6378 scope
@@ -136,12 +151,34 @@ SUITE( fbc_tests.optimizations.inline_ops )
136151 CU_ASSERT_DOUBLE_EQUAL( int( v ), floor( v ), EPSILON_DBL )
137152 next
138153
154+ END_TEST
155+
156+
157+ '' transcendental tests
158+
159+ #ifdef __FB_DOS__
160+ '' djgpp's math lib has an implementation that requires 2 * EPSILON_SNG to
161+ '' pass the single asin() tests, we could increase epsilon, or calculate with
162+ '' alternate asin() function
163+ # if ENABLE_CHECK_BUGS
164+ #define alt_asin asinf
165+ # else
166+ private function alt_asin( byval x as single ) as single
167+ function = atan2(x, sqr( 1! - x*x ))
168+ end function
169+ # endif
170+ # else
171+ #define alt_asin asinf
172+ # endif
173+
174+ TEST( transcendental )
175+
139176 for v as single = - 1 to 1 step . 01
140177 CU_ASSERT_DOUBLE_EQUAL( frac( v ), (v - hFixF( v )) , EPSILON_SNG )
141178 CU_ASSERT_DOUBLE_EQUAL( fix( v ), hFixF( v ), EPSILON_SNG )
142- CU_ASSERT_DOUBLE_EQUAL( sin( v ), sinf( v ), EPSILON_SNG )
143- CU_ASSERT_DOUBLE_EQUAL( asin( v ), asinf ( v ), EPSILON_SNG )
144- CU_ASSERT_DOUBLE_EQUAL( cos( v ), cosf( v ), EPSILON_SNG )
179+ CU_ASSERT_DOUBLE_EQUAL( sin( v ), sinf( v ), EPSILON_SNG_FPU )
180+ CU_ASSERT_DOUBLE_EQUAL( asin( v ), alt_asin ( v ), EPSILON_SNG )
181+ CU_ASSERT_DOUBLE_EQUAL( cos( v ), cosf( v ), EPSILON_SNG_FPU )
145182 CU_ASSERT_DOUBLE_EQUAL( acos( v ), acosf( v ), EPSILON_SNG )
146183 CU_ASSERT_DOUBLE_EQUAL( tan( v ), tanf( v ), EPSILON_SNG )
147184 CU_ASSERT_DOUBLE_EQUAL( atn( v ), atanf( v ), EPSILON_SNG )
@@ -184,6 +221,86 @@ SUITE( fbc_tests.optimizations.inline_ops )
184221 b = 5.0
185222 CU_ASSERT_DOUBLE_EQUAL( atan2( a, b ), atan2_( a, b ), EPSILON_DBL )
186223 end scope
224+
225+ END_TEST
226+
227+
228+ '' reciprocal
229+
230+ type TDIV
231+ __ as integer
232+ end type
233+ operator / ( byval x as single , byref y as const TDIV ) as single
234+ operator = 888 '' cook a value to test with
235+ end operator
236+
237+ type TSQR
238+ __ as integer
239+ end type
240+ operator sqr ( byref x as const TSQR ) as single
241+ operator = 16 '' cook a value to test with
242+ end operator
243+
244+ TEST( reciprocal )
245+
246+ '' in some modes (i.e. -gen gas -fpmode fast -fpu sse )
247+ '' AST optimizer will replace expressions with equivalent
248+ '' reciprocal instructions. We can't prove that the
249+ '' optimization actually took place unless we look at the
250+ '' ASM/C code generated, but we can prove that fb code has
251+ '' valid results for all forms.
252+
253+ scope
254+ '' 1! / single
255+ dim x as single = 5
256+ dim r as single
257+ r = 1! / x
258+ CU_ASSERT_DOUBLE_EQUAL( r, 0.2 , EPSILON_SNG_FPU )
259+ end scope
260+
261+ scope
262+ '' 1! / double
263+ dim x as double = 5
264+ dim r as single
265+ r = 1! / x
266+ CU_ASSERT_DOUBLE_EQUAL( r, 0.2 , EPSILON_SNG )
267+ end scope
268+
269+ scope
270+ '' 1! / integer
271+ dim x as integer = 5
272+ dim r as single
273+ r = 1! / x
274+ CU_ASSERT_DOUBLE_EQUAL( r, 0.2 , EPSILON_SNG )
275+ end scope
276+
277+ scope
278+ '' 1! / sqr(number)
279+ dim x as single = 0.0025
280+ dim r as single
281+ r = 1! / sqr(x)
282+ CU_ASSERT_DOUBLE_EQUAL( r, 20 , EPSILON_SNG )
283+ end scope
284+
285+ '' For overloaded / and SQR(), prove that the
286+ '' optimization is not used.
287+
288+ scope
289+ '' 1! / UDT
290+ dim x as TDIV
291+ dim r as single
292+ r = 1! / x
293+ CU_ASSERT_DOUBLE_EQUAL( r, 888 , EPSILON_SNG )
294+ end scope
295+
296+ scope
297+ '' 1! / SQR(UDT)
298+ dim x as TSQR
299+ dim r as single
300+ r = 1! / sqr(x)
301+ CU_ASSERT_DOUBLE_EQUAL( r, 0.0625 , EPSILON_SNG_FPU )
302+ end scope
303+
187304 END_TEST
188305
189306END_SUITE
0 commit comments