Skip to content

Commit 791f00d

Browse files
authored
Merge pull request #76 from jayrm/sqrt-overload
Allow overload operator SQR()
2 parents 57a9e15 + abc1c84 commit 791f00d

File tree

9 files changed

+174
-26
lines changed

9 files changed

+174
-26
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Version 1.06.0
1111
- Windows API binding updated to additionally support _WIN32_WINNT &h0501, &h0600, &h0601
1212
- Under X11, ScreenControl GET_WINDOW_HANDLE places the Display ptr in param2
1313
- Updated bindings: SDL2 2.0.6, SDL2_image 2.0.1, SDL2_mixer 2.0.1, SDL2_net 2.0.1, SDL2_ttf 2.0.14
14+
- allow overload operator SQR()
1415

1516
[fixed]
1617
- win/d3dx9.bi no longer has a hard-coded #inclib "d3dx9d". d3dx9d.dll is apparently not a generally valid choice. In practice programs have to be linked against d3dx9_33.dll or d3dx9_39.dll, etc.

src/compiler/ast-optimize.bas

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,19 +1739,22 @@ private function hOptReciprocal _
17391739
if( astIsCONST( l ) ) then
17401740
if( (astGetDataType( l ) = FB_DATATYPE_SINGLE) andalso (astConstGetFloat( l ) = 1.0) ) then
17411741
r = n->r
1742-
if( astIsUOP( r, AST_OP_SQRT ) ) then
1743-
'' change this to a rsqrt
1744-
*n = *r
1745-
n->class = AST_NODECLASS_UOP
1746-
n->op.op = AST_OP_RSQRT
1747-
astDelNode( r )
1748-
astDelNode( l )
1749-
elseif( astGetDataType( r ) = FB_DATATYPE_SINGLE ) then
1750-
'' change this to a rcp
1751-
astDelNode( n )
1752-
n = astNewUOP( AST_OP_RCP, r )
1753-
astDelNode( l )
1754-
end if
1742+
select case as const astGetDataClass( r )
1743+
case FB_DATACLASS_INTEGER, FB_DATACLASS_FPOINT
1744+
if( astIsUOP( r, AST_OP_SQRT ) ) then
1745+
'' change this to a rsqrt
1746+
*n = *r
1747+
n->class = AST_NODECLASS_UOP
1748+
n->op.op = AST_OP_RSQRT
1749+
astDelNode( r )
1750+
astDelNode( l )
1751+
elseif( astGetDataType( r ) = FB_DATATYPE_SINGLE ) then
1752+
'' change this to a rcp
1753+
astDelNode( n )
1754+
n = astNewUOP( AST_OP_RCP, r )
1755+
astDelNode( l )
1756+
end if
1757+
end select
17551758
end if
17561759
end if
17571760
end if

src/compiler/parser-assignment.bas

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function cOperator( byval is_overload as integer ) as integer
6565
FB_TK_ABS, FB_TK_SGN, FB_TK_FIX, FB_TK_FRAC, _
6666
FB_TK_INT, FB_TK_EXP, FB_TK_LOG, FB_TK_SIN, _
6767
FB_TK_ASIN, FB_TK_COS, FB_TK_ACOS, FB_TK_TAN, _
68-
FB_TK_ATN, FB_TK_LEN, _
68+
FB_TK_ATN, FB_TK_SQR, FB_TK_LEN, _
6969
FB_TK_ADDROFCHAR, FB_TK_FIELDDEREF, CHAR_LBRACKET, _
7070
FB_TK_NEW, FB_TK_DELETE, _
7171
FB_TK_FOR, FB_TK_STEP, FB_TK_NEXT
@@ -99,6 +99,7 @@ function cOperator( byval is_overload as integer ) as integer
9999
case FB_TK_ACOS : op = AST_OP_ACOS
100100
case FB_TK_TAN : op = AST_OP_TAN
101101
case FB_TK_ATN : op = AST_OP_ATAN
102+
case FB_TK_SQR : op = AST_OP_SQRT
102103
case FB_TK_LEN : op = AST_OP_LEN
103104
case FB_TK_ADDROFCHAR : op = AST_OP_ADDROF
104105
case FB_TK_FIELDDEREF : op = AST_OP_FLDDEREF

src/compiler/symb-mangling.bas

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,9 @@ private function hGetOperatorName( byval proc as FBSYMBOL ptr ) as const zstring
10671067
case AST_OP_ATAN
10681068
function = @"v13atn"
10691069

1070+
case AST_OP_SQRT
1071+
function = @"v13sqr"
1072+
10701073
case AST_OP_NEW, AST_OP_NEW_SELF
10711074
function = @"nw"
10721075

tests/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ all :
8989
@$(ECHO) " ARCH=arch (default is 486)"
9090
@$(ECHO) " OS=DOS"
9191
@$(ECHO) " FPU=fpu | sse"
92+
@$(ECHO) " FPMODE=fast | precise"
93+
@$(ECHO) " GEN=gas | gcc"
9294
@$(ECHO) " UNITTEST_RUN_ARGS=args"
9395
@$(ECHO) " ENABLE_CHECK_BUGS=1"
9496
@$(ECHO) " ENABLE_CONSOLE_OUTPUT=1"

tests/optimizations/consteval.bas

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,28 @@ SUITE( fbc_tests.optimizations.consteval )
77

88
const EPSILON_SNG as single = 1.19290929e-7
99

10+
'' fast floating point is NOT precise, the compiler should have been
11+
'' built with -fpmode precise, so we may have differences when
12+
'' comparing const evaulation and runtime evaluation
13+
14+
#if __FB_FPMODE__ = "fast"
15+
const EPSILON_SNG_FPU as single = EPSILON_SNG * 1000
16+
#else
17+
const EPSILON_SNG_FPU as single = EPSILON_SNG
18+
#endif
19+
1020
#macro checkUop( func, value )
1121
f = value
1222
CU_ASSERT_DOUBLE_EQUAL( func( value ), func( f ), EPSILON_SNG )
1323
CU_ASSERT_DOUBLE_EQUAL( func( f ), func( value ), EPSILON_SNG )
1424
#endmacro
1525

26+
#macro checkUopFPU( func, value )
27+
f = value
28+
CU_ASSERT_DOUBLE_EQUAL( func( value ), func( f ), EPSILON_SNG_FPU )
29+
CU_ASSERT_DOUBLE_EQUAL( func( f ), func( value ), EPSILON_SNG_FPU )
30+
#endmacro
31+
1632
'' -
1733
f = 1.0f : CU_ASSERT_DOUBLE_EQUAL( (- 1.0f), (- f) , EPSILON_SNG )
1834
f = -1.0f : CU_ASSERT_DOUBLE_EQUAL( (- 1.0f), f , EPSILON_SNG )
@@ -26,20 +42,20 @@ SUITE( fbc_tests.optimizations.consteval )
2642
CU_ASSERT_EQUAL( sgn( 0.0f ), 0 )
2743
CU_ASSERT_EQUAL( sgn( -1.0f ), -1 )
2844
'' sin
29-
checkUop( sin, 1.0f )
30-
checkUop( sin, 0.5f )
31-
checkUop( sin, -0.5f )
32-
checkUop( sin, -1.0f )
45+
checkUopFPU( sin, 1.0f )
46+
checkUopFPU( sin, 0.5f )
47+
checkUopFPU( sin, -0.5f )
48+
checkUopFPU( sin, -1.0f )
3349
'' asin
3450
checkUop( asin, 1.0f )
3551
checkUop( asin, 0.5f )
3652
checkUop( asin, -0.5f )
3753
checkUop( asin, -1.0f )
3854
'' cos
39-
checkUop( cos, 1.0f )
40-
checkUop( cos, 0.5f )
41-
checkUop( cos, -0.5f )
42-
checkUop( cos, -1.0f )
55+
checkUopFPU( cos, 1.0f )
56+
checkUopFPU( cos, 0.5f )
57+
checkUopFPU( cos, -0.5f )
58+
checkUopFPU( cos, -1.0f )
4359
'' acos
4460
checkUop( acos, 1.0f )
4561
checkUop( acos, 0.5f )

tests/optimizations/inline-ops.bas

Lines changed: 121 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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 = &h8000000000000000ll : 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

189306
END_SUITE

tests/structs/ops.bas

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ SUITE( fbc_tests.structs.ops )
3232
makeop(INT)
3333
makeop(EXP)
3434
makeop(LOG)
35+
makeop(SQR)
3536
makeop(SIN)
3637
makeop(ASIN)
3738
makeop(COS)
@@ -74,6 +75,7 @@ SUITE( fbc_tests.structs.ops )
7475
testop(INT)
7576
testop(EXP)
7677
testop(LOG)
78+
testop(SQR)
7779
testop(SIN)
7880
testop(ASIN)
7981
testop(COS)

tests/unit-tests.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ endif
9696
ifneq ($(FPU),)
9797
FBC_CFLAGS += -fpu $(FPU)
9898
endif
99+
ifneq ($(FPMODE),)
100+
FBC_CFLAGS += -fpmode $(FPMODE)
101+
endif
99102
ifneq ($(GEN),)
100103
FBC_CFLAGS += -gen $(GEN)
101104
endif

0 commit comments

Comments
 (0)