Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by MrSwiss »

Two working versions:

Code: Select all

Function LeapYear(ByVal yea As ULong) As Boolean
    If (yea Mod 4) Then Return FALSE    ' definitely NOT a leap Year
    ' below: exception test (a century but, not also clean dividable by 400)
    If Not CBool(yea Mod 100) AndAlso CBool(yea Mod 400) Then Return FALSE
    ' below: all tests passed = it is, a leap Year
    Return TRUE
End Function

Code: Select all

Function LeapYear(ByVal yea As ULong) As Boolean
    If (yea Mod 4) Then Return FALSE    ' definitely NOT a leap Year
    ' below: exception test (a century but, not also clean dividable by 400)
    If (yea Mod 100 = 0) AndAlso (yea Mod 400 <> 0) Then Return FALSE
    ' below: all tests passed = it is, a leap Year
    Return TRUE
End Function
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by Munair »

If you want speed optimization then the following shortcut is allowed, which would make the code slightly faster when iterating through a long range of years, throwing away three years out of four:

Code: Select all

function LeapYear(byval y as ulong) as boolean
	if (y mod 4) = 0 then
		if (y mod 100) <> 0 or (y mod 400) = 0 then
			return true
		end if
	end if
	return false
end function
However, the asm code proceduced here is 88 lines, whereas my first example produces 86 lines. In this case I would go for the second example, but often we have to compromise: faster code or smaller size.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by MrSwiss »

Why don't you simply run some speed tests ...
I've made them ... see this thread
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by Munair »

MrSwiss wrote:Why don't you simply run some speed tests ...
I've made them ...
When the result is negative, there is no difference in speed. But two 'return false' statements produce larger code. The explicit boolean conversions however slow things down. There is no need for it as modulo operations are mathematical and should be tested for zero or non zero, which isn't the same as true or false. They only become true or false when we test the result and decide what to do with it: zero can be true or false and non-zero can be true or false. So your example actually generates two boolean results, which slows things and generate larger code: 93 lines against 86 or 88, whatever one prefers.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by MrSwiss »

Munair wrote:... zero can be true or false and non-zero can be true or false.
Which is NOT true, in FB:
FALSE is always numeric: 0, while TRUE is (Not FALSE), anything that differs from: 0.

Boolean Variables: either: 0 = FALSE, or +1/-1 = TRUE (+1 behind the scenes, -1 in front).
This allows: 'Boolean' = Not 'Boolean' (to simply invert), instead of: If ... Then ... Else ...

Btw: counting code lines is sensless (even in ASM), since instructions differ in CPU-count,
needed to execute ... (by far not the same, as a speed test).
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by Munair »

What I was trying to say is that the result of a numerical operation is not boolean, unless we test it. There are programming languages where it is not possible to evaluate BOOLVAR = (A MOD B) because they are different data types. BASIC languages have usually been very flexible in this regard and most programmers have grown accustomed to it. The agreement that FALSE = 0 has nothing to do with a numerical operation resulting in 0. It's just convient to make the test this way. If one day FALSE and TRUE would switch (although unlikely) a lot of code would have to be rewritten. ;)
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by jj2007 »

MrSwiss wrote:
dodicat wrote:A macro would do for leap year. But it's a long wait to be really sure.
(I've modified your macro somewhat) ... :

Code: Select all

#Define IsLeapYear(N)   CBool( (N Mod 4 = 0 Andalso N Mod 100 <> 0) OrElse (N Mod 400 = 0) )
That could be interesting for some timing tests. Here is the disassembly (M like 'Macro')):

Code: Select all

#Define IsLeapYearM(N)   CBool( (N Mod 4 = 0 Andalso N Mod 100 <> 0) OrElse (N Mod 400 = 0) )
 	...
 	asm int 3		' -------- embed the code in two markers ------
 	asm int 3
 	lyb=IsLeapYearM(n)
 	asm int 3
 	asm int 3		' -------- embed the code in two markers ------
Now we have a look under the hood:

Code: Select all

  int3
  int3
  mov ebx, [ebp-1C]
  mov ecx, 4
  mov eax, ebx
  cdq
  idiv ecx
  mov eax, edx
  mov ebx, eax
  test ebx, ebx
  jnz short 0040179E
  mov ebx, [ebp-1C]
  mov ecx, 64
  mov eax, ebx
  cdq
  idiv ecx
  mov eax, edx
  mov ebx, eax
  test ebx, ebx
  setnz bl
  shr ebx, 1
  sbb ebx, ebx
  mov [ebp-20], ebx
  jmp short 004017A5
  mov dword ptr [ebp-20], 0
  cmp dword ptr [ebp-20], 0
  jne short 004017CA
  mov ebx, [ebp-1C]
  mov ecx, 190
  mov eax, ebx
  cdq
  idiv ecx
  mov eax, edx
  mov ebx, eax
  test ebx, ebx
  setz bl
  shr ebx, 1
  sbb ebx, ebx
  mov [ebp-24], ebx
  jmp short 004017D1
  mov dword ptr [ebp-24], -1
  cmp dword ptr [ebp-24], 0
  setne bl
  movzx eax, bl
  neg eax
  mov [ebp-0C], eax
  int3
  int3
The two idivs are horribly slow btw. This can be done a factor 4 faster.
Last edited by jj2007 on Nov 11, 2017 2:39, edited 1 time in total.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by Munair »

jj2007 wrote:
MrSwiss wrote:
dodicat wrote:A macro would do for leap year. But it's a long wait to be really sure.
(I've modified your macro somewhat) ... :

Code: Select all

#Define IsLeapYear(N)   CBool( (N Mod 4 = 0 Andalso N Mod 100 <> 0) OrElse (N Mod 400 = 0) )
That could be interesting for some timing tests. Here is the disassembly (M like 'Macro')):

Code: Select all

#Define IsLeapYearM(N)   CBool( (N Mod 4 = 0 Andalso N Mod 100 <> 0) OrElse (N Mod 400 = 0) )
 	...
 	asm int 3		' -------- embed the code in two markers ------
 	asm int 3
 	lyb=IsLeapYearM(n)
 	asm int 3
 	asm int 3		' -------- embed the code in two markers ------
Now we have a look under the hood:

Code: Select all

  int3
  int3
  mov ebx, [ebp-1C]
  mov ecx, 4
  mov eax, ebx
  cdq
  idiv ecx
  mov eax, edx
  mov ebx, eax
  test ebx, ebx
  jnz short 0040179E
  mov ebx, [ebp-1C]
  mov ecx, 64
  mov eax, ebx
  cdq
  idiv ecx
  mov eax, edx
  mov ebx, eax
  test ebx, ebx
  setnz bl
  shr ebx, 1
  sbb ebx, ebx
  mov [ebp-20], ebx
  jmp short 004017A5
  mov dword ptr [ebp-20], 0
  cmp dword ptr [ebp-20], 0
  jne short 004017CA
  mov ebx, [ebp-1C]
  mov ecx, 190
  mov eax, ebx
  cdq
  idiv ecx
  mov eax, edx
  mov ebx, eax
  test ebx, ebx
  setz bl
  shr ebx, 1
  sbb ebx, ebx
  mov [ebp-24], ebx
  jmp short 004017D1
  mov dword ptr [ebp-24], -1
  cmp dword ptr [ebp-24], 0
  setne bl
  movzx eax, bl
  neg eax
  mov [ebp-0C], eax
  int3
  int3
The two idivs are horribly slow btw. This can be done a factor 10 faster.
I used this algorithm in a test I ran to see what code would be fastest. Indeed, this macro was almost twice as slow as the other algorithms. I will post the test with results shortly.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by jj2007 »

Munair wrote:I will post the test with results shortly.
Proposal for a testbed:

Code: Select all

  dim as double t=timer
  dim as long lym
  lym=0
  for n as long=1 to 400000000
	if IsLeapYearM(n) then lym=lym+1
  next
  print timer-t;" seconds for finding ";lym;" leap years"
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Data-Type, conversion Array's and Overloaded Function's (in a nutshell)

Post by Munair »

jj2007 wrote:
Munair wrote:I will post the test with results shortly.
Proposal for a testbed:

Code: Select all

  dim as double t=timer
  dim as long lym
  lym=0
  for n as long=1 to 400000000
	if IsLeapYearM(n) then lym=lym+1
  next
  print timer-t;" seconds for finding ";lym;" leap years"
I posted my test results with code here: viewtopic.php?f=7&t=25305&start=15#p239108
Post Reply