Detecting Math Errors

General FreeBASIC programming questions.
Post Reply
Twylyght
Posts: 9
Joined: Jul 29, 2023 15:51

Detecting Math Errors

Post by Twylyght »

How would I detect when calculations produce errors such as overflow type errors? They don't seem to give a nonzero result in Err(), or maybe I need to do something to turn this type of checking on?

EG when this code starts returning 1.#INF:

Code: Select all

dim I as Single

I=1

Do
   I=I*2
   Print I
   Sleep 100
loop
Or this code returns -9223372036854775808:

Code: Select all

dim I as Integer

I=1

Do
   I=I*2
   Print I
   Sleep 100
loop Until I = 0

Sleep
Jattenalle
Posts: 66
Joined: Nov 17, 2023 14:41
Contact:

Re: Detecting Math Errors

Post by Jattenalle »

Overflow UINTEGER addition implementation:

Code: Select all

Function addOverflowInteger(ByVal lhs As uinteger, ByVal rhs As uinteger, byref result as uinteger) As boolean
	function = TRUE
	result = lhs + rhs
	Asm
		jc overflow
		mov [Function], FALSE
		overflow:
	End Asm
End Function

dim as uinteger result
dim as uinteger l, r
l	=	5
r	=	10
if addOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if
l	=	2000000000
r	=	2000000000
if addOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if
l	=	4000000000
r	=	1000000000
if addOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if
l	=	9000000000000000000
r	=	9000000000000000000
if addOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if
l	=	18000000000000000000
r	=	1000000000000000000
if addOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if
IsNaN SINGLE implementation:

Code: Select all

const C_IND		=	acos(1.00000001d)
const C_INF		=	1 / 0
const C_NINF	=	-1 / 0
Function IsNaN(f As Single) As Boolean
	if (f = C_INF or f = C_NINF) then
		return -1
	end if
	Dim As ulong ptr raw = cptr(ulong ptr, @f)
	Return ((*raw And &H7F800000) = &H7F800000) And (*raw And &H007FFFFF) <> 0
End Function

dim as single n

n = 10
if IsNaN(n) then '// False, it's a number
	print n &" is NaN!"
end if
n = C_INF
if IsNaN(n) then
	print n &" is NaN!"
end if
n = C_NINF
if IsNaN(n) then
	print n &" is NaN!"
end if
n = C_IND
if IsNaN(n) then
	print n &" is NaN!"
end if
n = 3489573894573534957
if IsNaN(n) then '// False, it's a number!
	print n &" is NaN!"
end if
For checking SIGNED INTEGER overflow you can just compare the sign:

Code: Select all

function signedAddOverflowInteger(byval lhs as integer, byval rhs as integer, byref result as integer) as boolean
	result = lhs + rhs
	if sgn(result) <> sgn(lhs) then
		return TRUE
	end if
	return FALSE
end function

dim as integer result
dim as integer l, r

l = 10
r = 10
if signedAddOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if

l = 9000000000000000000
r = 9000000000000000000
if signedAddOverflowInteger(l, r, result) then
	print "ERR: Overflow when adding "& l &" + "& r &"!"
else
	print ""& l &" + "& r &" = "& result
end if
Twylyght
Posts: 9
Joined: Jul 29, 2023 15:51

Re: Detecting Math Errors

Post by Twylyght »

Thank you. Is it possible to describe what this is accomplishing:
Jattenalle wrote: Jan 04, 2025 15:10 ((*raw And &H7F800000) = &H7F800000) And (*raw And &H007FFFFF) <> 0
I mean, I get that it's doing something with bit masks. I think.
Jattenalle
Posts: 66
Joined: Nov 17, 2023 14:41
Contact:

Re: Detecting Math Errors

Post by Jattenalle »

Twylyght wrote: Jan 04, 2025 15:34 Thank you. Is it possible to describe what this is accomplishing:
Jattenalle wrote: Jan 04, 2025 15:10 ((*raw And &H7F800000) = &H7F800000) And (*raw And &H007FFFFF) <> 0
I mean, I get that it's doing something with bit masks. I think.
It's checking for the specific bitmasks that corresponds to IEEE float definitions for invalid floats.
Twylyght
Posts: 9
Joined: Jul 29, 2023 15:51

Re: Detecting Math Errors

Post by Twylyght »

Jattenalle wrote: Jan 05, 2025 13:05 It's checking for the specific bitmasks that corresponds to IEEE float definitions for invalid floats.
So, would I need to change that for a DOUBLE implementation? If so, how?

Sorry, I didn't know there'd be different answers for every different data type. I did use the basic comparison to 1/0 and -1/0 and that worked nicely.
Jattenalle
Posts: 66
Joined: Nov 17, 2023 14:41
Contact:

Re: Detecting Math Errors

Post by Jattenalle »

Twylyght wrote: Jan 05, 2025 13:17
Jattenalle wrote: Jan 05, 2025 13:05 It's checking for the specific bitmasks that corresponds to IEEE float definitions for invalid floats.
So, would I need to change that for a DOUBLE implementation? If so, how?

Sorry, I didn't know there'd be different answers for every different data type. I did use the basic comparison to 1/0 and -1/0 and that worked nicely.
For DOUBLE you just need to extend the check to cover all 64bits, here's both SINGLE and DOUBLE implemented as OVERLOADED functions:

Code: Select all

Function IsNaN overload(f as Single) as Boolean
	if (f = (1 / 0) or f = (-1 / 0)) then
		return -1
	end if
	return ((*cptr(ulong ptr, @f) and &H7F800000) = &H7F800000) and (*cptr(ulong ptr, @f) and &H007FFFFF) <> 0
End Function
Function IsNaN(f as double) as Boolean
	if (f = (1 / 0) or f = (-1 / 0)) then
		return -1
	end if
	return ((*cptr(ulongint ptr, @f) and &H7F80000000000000ull) = &H7F80000000000000ull) and (*cptr(ulongint ptr, @f) and &H007FFFFFFFFFFFFFull) <> 0
End Function

dim as single n

print "===== SINGLE ====="
n = 10
if IsNaN(n) then '// False, it's a number
	print n &" is NaN!"
end if
n = 1 / 0
if IsNaN(n) then
	print n &" is NaN!"
end if
n = -1 / 0
if IsNaN(n) then
	print n &" is NaN!"
end if
n = acos(1.00000001d)
if IsNaN(n) then
	print n &" is NaN!"
end if
n = 3489573894573534957
if IsNaN(n) then '// False, it's a number!
	print n &" is NaN!"
end if

print "===== DOUBLE ====="
dim as double d
d = 10
if IsNaN(d) then '// False, it's a number
	print d &" is NaN!"
end if
d = 1 / 0
if IsNaN(d) then
	print d &" is NaN!"
end if
d = -1 / 0
if IsNaN(d) then
	print d &" is NaN!"
end if
d = acos(1.00000001d)
if IsNaN(d) then
	print d &" is NaN!"
end if
d = 3489573894573534957
if IsNaN(d) then '// False, it's a number!
	print d &" is NaN!"
end if
Twylyght
Posts: 9
Joined: Jul 29, 2023 15:51

Re: Detecting Math Errors

Post by Twylyght »

Thanks for the help.
Post Reply