The MASM Forum

General => The Workshop => Topic started by: zedd151 on February 23, 2025, 01:45:36 AM

Title: Sieve of Eratosthenes several variations
Post by: zedd151 on February 23, 2025, 01:45:36 AM
Changed the topic title, to reflect that several variations are available in this topic, by several authors. If you have a different Prime Sieve, post your code here and join the phun. :biggrin:

My 32 bit (original) version of Sieve of Eratosthenes... (added message box, if array not allocated.)

    include \masm32\include\masm32rt.inc
   
    .data
   
    pTbl        dd 0                    ; <-- pointer to byte array
    arrsize    dd 1000000
    curnumber  dd 0                    ; <-- current number for our sieve algo
   
    .code
start:
   
    invoke GlobalAlloc, GPTR, arrsize  ; <-- allocate memory for table and prime numbers
  .if eax == 0                          ; <-- if not enough memory for array size, display message and exit
 
    fn MessageBox, 0, "Not enough memory to create array", 0, 0
    jmp noarray
  .endif
    mov pTbl, eax
   
    push edi
    mov edi, pTbl                      ; temporarily put ptr to array in edi, for stosb
    mov eax, 01010101h
    mov ecx, arrsize
    shr ecx, 2
    rep stosd                          ; <-- initialize the table to '1'
    pop edi                            ; <-- restore edi to previous value
    mov esi, pTbl                      ; <-- we put ptr to array into esi :)
   
    xor eax, eax
    mov curnumber, 2                    ; <-- exluding '0' and '1', as neither are prime
    add eax, curnumber                  ; <-- exclude the first iteration of sequence
                                        ; <-- else we will have no primes listed
  @@:
    add eax, curnumber                  ; <-- get multiples for this iteration
    cmp eax, arrsize                    ; <-- check if end of array is reached, exit
    jae done1                          ;    loop if yes.
    cmp byte ptr [esi+eax], 0          ; <-- check if array location is already marked
    jz @b
    mov byte ptr [esi+eax], 0          ; <-- if not marked, we mark it now
    jmp @b
   
  done1:
    inc curnumber                      ; <-- increment current number
    mov eax, curnumber                  ; <-- move it into register
    cmp eax, arrsize                    ; <-- check if at array end
    jae done2                          ; <-- jump to next process, if array end
    xor eax, eax                        ;    else increment to next number
    add eax, curnumber
    jmp @b                              ; <-- jump back into the processing loop
   
  done2:
    mov edi, 2                          ; <--- skip over '0' and '1'
  @@:
   
    cmp byte ptr [esi+edi], 1          ; <--- if byte == zero, not prime, don't print
    jnz noprint
   
    mov eax, ustr$(edi)                ; <--- convert our current prime to ascii decimal string
   
    pushad                              ; <--- save all the registers

    print eax, 0Dh, 0Ah, 0
   
    popad                              ; <--- restore the registers
   
  noprint:
    inc edi
    cmp edi, arrsize
    jl @b                              ; <--- loop back to get more primes to print
    invoke GlobalFree, pTbl            ; <--- free the memory used

  noarray:                              ; <--- jump here to exit, if memory not allocated
    invoke ExitProcess, 0
end start

Use the included "makeit.bat" to assemble and link it, and "RunIt.bat" to run the program, generate file "primes32.txt", and open the .txt file with qeditor.

You're Welcome.  :biggrin:
Title: Re: Sieve of Eratosthenes
Post by: jj2007 on February 23, 2025, 11:03:21 AM
Great stuff, Zedd :thumbsup:
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 23, 2025, 11:19:22 AM
Quote from: jj2007 on February 23, 2025, 11:03:21 AMGreat stuff, Zedd :thumbsup:
Thanks, but it is actually old code, I found it recently ('prime' was nowhere in its original name  :tongue: ). Previously, I only knew where my more recent 64 bit version was.  :smiley:
Title: Re: Sieve of Eratosthenes
Post by: FORTRANS on February 24, 2025, 01:21:14 AM
Hi,

   I wrote a program to display primes as white pixels on a
black background.  I varied the width of the picture to look
for "patterns" that would show up at times.  A fun, if a bit
crude, exercise.  A DOS program with VESA graphics.  Humans
can see (false) patterns in some random data.

Cheers,

Steve N.
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 01:35:43 AM
Quote from: FORTRANS on February 24, 2025, 01:21:14 AMHi,

  I wrote a program to display primes as white pixels on a
black background.  I varied the width of the picture to look
for "patterns" that would show up at times.  A fun, if a bit
crude, exercise.  A DOS program with VESA graphics.  Humans
can see (false) patterns in some random data.

Cheers,

Steve N.
Hi Steve. Interesting. I am sure that daydreamer would like to see that code, if it is still available. Magnus (daydreamer) has been experimenting with displaying the primes as a bitmap. Seems very similar to your idea, unless of course I misunderstood Magnus' discussion and intention regarding prime numbers and using bitmaps.
Magnus? What say you?
Title: Re: Sieve of Eratosthenes
Post by: daydreamer on February 24, 2025, 03:48:55 AM
Quote from: zedd151 on February 24, 2025, 01:35:43 AM
Quote from: FORTRANS on February 24, 2025, 01:21:14 AMHi,

  I wrote a program to display primes as white pixels on a
black background.  I varied the width of the picture to look
for "patterns" that would show up at times.  A fun, if a bit
crude, exercise.  A DOS program with VESA graphics.  Humans
can see (false) patterns in some random data.

Cheers,

Steve N.
Hi Steve. Interesting. I am sure that daydreamer would like to see that code, if it is still available. Magnus (daydreamer) has been experimenting with displaying the primes as a bitmap. Seems very similar to your idea, unless of course I misunderstood Magnus' discussion and intention regarding prime numbers and using bitmaps.
Magnus? What say you?
here is 1 bit/pixel bitmap drawing/output I was going to use as starting point
512kb*8 pixels/byte and few bytes overhead its possible to store lots of primes
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 04:15:38 AM
I had to fix the path for "ptexture.inc", and used "console assemble and link".

Well, at least its a start. The resulting bmp looks like a two lane highway,  :tongue:
Now to implement this bitmap code in your prime numbers code for display.  :biggrin:
Title: Re: Sieve of Eratosthenes
Post by: TimoVJL on February 24, 2025, 04:27:23 AM
Quote from: zedd151 on February 24, 2025, 04:15:38 AMWell, at least its a start. The resulting bmp looks like a two lane highway,  :tongue:
After earthquake  :biggrin:
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 04:39:30 AM
Quote from: TimoVJL on February 24, 2025, 04:27:23 AM
Quote from: zedd151 on February 24, 2025, 04:15:38 AMWell, at least its a start. The resulting bmp looks like a two lane highway,  :tongue:
After earthquake  :biggrin:
lol
I'm pretty sure that Magnus was just testing the drawing functions and bitmap creation code prior to using those in the (hopefully near) future, for his prime number code.
Title: Re: Sieve of Eratosthenes
Post by: daydreamer on February 24, 2025, 06:12:47 AM
Quote from: zedd151 on February 24, 2025, 04:39:30 AM
Quote from: TimoVJL on February 24, 2025, 04:27:23 AM
Quote from: zedd151 on February 24, 2025, 04:15:38 AMWell, at least its a start. The resulting bmp looks like a two lane highway,  :tongue:
After earthquake  :biggrin:
lol
I'm pretty sure that Magnus was just testing the drawing functions and bitmap creation code prior to using those in the (hopefully near) future, for his prime number code.
its reusing code I developed from Dos 13h 16bit code drawing different road tiles ->32bit code writing to .bmps instead
its already have compressing from a byte buffer to bits = 1/8 smaller data in writebmp proc
2 gb memory =17 179 869 184 pixels
3.8 gb memory 32 641 751 449 pixels




Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 06:20:36 AM
Quote from: daydreamer on February 24, 2025, 06:12:47 AMits reusing code I developed from Dos 13h 16bit code drawing different road tiles ->32bit code writing to .bmps instead
Okay.  :thumbsup: 
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 24, 2025, 06:45:30 AM
Here's my version, a li'l console program. Just spits the prime #s out with no formatting (left as an exercise for the reader).
A little neater than some other examples, perhaps.

;============================================
; -- Sieve of Erastothenes --
;
;============================================

.nolist
include \masm32\include\masm32rt.inc
.list

;============================================
; Defines, structures, prototypes, etc.
;============================================

Sieve PROTO maxNum:DWORD, primeBuffPtr:DWORD

$primeMarker EQU -1 ;Marker to indicate a prime # in buffer.
$CRLF EQU <13, 10>
$tab EQU 9


;============================================
; HERE BE DATA
;============================================
.data

UsageMsg DB $CRLF, "Usage: sieveoferastothenes #", $CRLF
DB $tab, "where ""#"" is the maximum # to search for primes.", $CRLF, $CRLF, 0

;============================================
; UNINITIALIZED DATA
;============================================
.data?

HeapHandle HANDLE ?
PrimeBuffer DD ? ;Base address of heap-allocated buffer.
CmdLineBuffer DB 256 DUP(?)


;============================================
; CODE LIVES HERE
;============================================
.code

start: CALL WinMain
INVOKE ExitProcess, 0


;====================================================================
; Mainline proc
;====================================================================

WinMain PROC
LOCAL maxNum:DWORD, currNum:DWORD, numBuffer[16]:BYTE

; Get max. prime # from command line:
INVOKE GetCL, 1, OFFSET CmdLineBuffer ;Get arg[1] from command line.
CMP EAX, 1 ;See how many args on CL.
JE getnum

; No arg. given, so show "usage" message:
INVOKE StdOut, OFFSET UsageMsg
JMP exit99

getnum: INVOKE atodw, OFFSET CmdLineBuffer
MOV maxNum, EAX

; Allocate a buffer for primes:
CALL GetProcessHeap
MOV HeapHandle, EAX

INVOKE HeapAlloc, EAX, 0, maxNum
MOV PrimeBuffer, EAX

; Find those primes!
INVOKE Sieve, maxNum, PrimeBuffer

; Show those primes!
MOV EBX, PrimeBuffer
MOV currNum, 1

showlp: CMP BYTE PTR [EBX], 0 ;Next # in prime buffer.
JE skip ;  Nope, skip it.
INVOKE dwtoa, currNum, ADDR numBuffer
INVOKE StdOut, ADDR numBuffer
MOV WORD PTR numBuffer, " " ;Put a space between #s.
INVOKE StdOut, ADDR numBuffer

skip: ADD currNum, 2
ADD EBX, 2 ;Skip all even #s.
MOV EAX, currNum
CMP EAX, maxNum
JBE showlp

INVOKE HeapFree, HeapHandle, 0, PrimeBuffer

exit99: RET

WinMain ENDP


;=========================================================================
; Sieve (maxNum, primeBuffPtr)
;
; Here's the Sieve of Erastothenes, a method of finding all prime #s in a
; given range.
;
; The buffer passed in and returned with all primes marked out starts at
; 1, not 0.
;
; Prime numbers in the buffer are marked with a value of -1 (0FFh).
;=========================================================================

Sieve PROC maxNum:DWORD, primeBuffPtr:DWORD

; Initialize prime buffer to all primes (mark with -1):
MOV ECX, maxNum
MOV EDX, primeBuffPtr
MOV AL, $primeMarker
initlp: MOV [EDX], AL
INC EDX
LOOP initlp

; Starting at #4, mark out all even #s as not prime:
MOV ECX, primeBuffPtr
MOV EDX, ECX
ADD ECX, maxNum ;Get our stopping point.
ADD EDX, 3 ;Point to #4 (buffer starts @ 1).
nxtevn: MOV BYTE PTR [EDX], 0 ;Mark as not prime.
ADD EDX, 2 ;Jump by 2s.
CMP EDX, ECX ;Continue until
JB nxtevn ;  we're @ end o'buffer.

; Here's the Sieve code: starting @ #3, mark out all multiples:
MOV EDX, primeBuffPtr
MOV ECX, 3 ;ECX = current number (start @ 3).
MOV EAX, ECX ;EAX = # to add to create multiples.
multlp: ADD ECX, EAX ;Next multiple.
CMP ECX, maxNum ;Are we at the end of buffer?
JA nxtmul ;  Yep, done with these multiples.
MOV BYTE PTR [EDX + ECX - 1], 0 ;  Nope, mark out as not prime.
JMP multlp ;Next multiple.

; Finished a set of multiples--go to next set:
nxtmul: ADD EAX, 2 ;Skip over even #s.
CMP EAX, maxNum ;Are we @ the last #?
JAE done ;  Yep, we be outta here.
MOV ECX, EAX ;  Else process that #s multiples.
JMP multlp

done: RET

Sieve ENDP

END start
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 07:16:17 AM
Seems a slight error in your version. '2' should be present as the only even number. '1' should not be there.
1
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
I replaced the " " (space) in your code with a single byte "0Dh" for carriage return for better printout.

Should be...
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 24, 2025, 07:17:32 AM
Ack. I forgot about 2!
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 07:19:28 AM
Quote from: NoCforMe on February 24, 2025, 07:17:32 AMAck. I forgot about 2!
:biggrin:   it happens.
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 24, 2025, 07:29:11 AM
Fixed it (problem was in display code, not the actual sieve code).
Now the display separator character is in an EQUate @ top of code, so easily changed.
One might want to write #s to a file instead.
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 07:30:26 AM
Quote from: NoCforMe on February 24, 2025, 07:29:11 AMOne might want to write #s to a file instead.
SieveOfErastothenes 1000>out.txt

'1' shouldn't be there. Yes I know it does not sound logical, given it is only divisible by itself or 1. But that's the way it is.

Prime numbers to 100 (https://www.dreambox.com/math/skills/numbers/prime-numbers#:~:text=The%20prime%20numbers%20up%20to,%2C%2083%2C%2089%2C%2097.), plus many, many other sources.
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 24, 2025, 07:40:49 AM
You're correct, of course.
Will fix it later ...
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 07:45:01 AM
Quote from: NoCforMe on February 24, 2025, 07:40:49 AMWill fix it later ...
Ok. Nice litte coding exercise though.  :smiley:
Title: Re: Sieve of Eratosthenes
Post by: FORTRANS on February 24, 2025, 09:10:05 AM
Hi,

Quote from: zedd151 on February 24, 2025, 01:35:43 AMHi Steve. Interesting. I am sure that daydreamer would like to see that code, if it is still available.

   Located the code.  Sieve code; 16-bit and I hardly recognize it.  Display code;
16-bit and VESA, mostly looks okay?.  Varying line length/picture width code;
nothing.  Save image code; nothing.  Some executables if you can run DOS plus
VESA Modes 103, 105, or 107?

Regards,

Steve
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 09:15:46 AM
Hi Steve. I only mentioned it because I thought that daydreamer (Magnus) might be interested in it. Not for me, I don't speak DOS, and certainly not VESA. I will let Magnus weigh in... he might want to see it. Thanks for digging through your archives though, Steve.
Title: Re: Sieve of Eratosthenes
Post by: sinsi on February 24, 2025, 11:14:18 AM
I would make one change to your original code
  done1:
    mov     eax,curnumber
  @10:
    inc     eax
    cmp     eax,arrsize
    jae     done2
    cmp     byte ptr [esi+eax],0
    jz      @10
    mov     curnumber,eax
    jmp     @b
   
  done2:
You don't need to chek every number. If you've marked off all multiples of 2 there's no need to do the same for 4, 6 ...

With a bigger buffer it runs noticeably quicker.
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 24, 2025, 11:30:17 AM
Yes. In my sieve code, after marking out all the even #s I start at 3 to eliminate multiples as non-primes, and advance my current # by 2 to skip all the even #s.
Title: Re: Sieve of Eratosthenes
Post by: sinsi on February 24, 2025, 11:41:09 AM
The same logic goes for 3s. If you've marked off 3, 6, 9... then no need to do 9, 18, 27... since the 3 takes care of them.
You mark off multiples of the next unmarked number.
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 01:05:55 PM
Quote from: sinsi on February 24, 2025, 11:14:18 AMYou don't need to chek every number. If you've marked off all multiples of 2 there's no need to do the same for 4, 6 ...

With a bigger buffer it runs noticeably quicker.
okay.  :smiley:  I *might* revisit the code at some point. But I am not young anymore. Time is something I do not have an abundance of, and I have many other projects that need to get finished, and fully working. This code at least, already does exactly what it is intended to do. Now if you were to tell me that the results contain errors, or the program crashes, then most likely  I would take care of that ASAP.  :smiley:
You can think of my code as a starting point, if you or anyone else would like to optimize it further, I would not complain.  :biggrin:
Title: Re: Sieve of Eratosthenes
Post by: sinsi on February 24, 2025, 01:36:56 PM
Quote from: zedd151 on February 24, 2025, 01:05:55 PMNow if you were to tell me that the results contain errors
I can't count that high :badgrin:
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 24, 2025, 01:52:06 PM
Quote from: sinsi on February 24, 2025, 01:36:56 PM
Quote from: zedd151 on February 24, 2025, 01:05:55 PMNow if you were to tell me that the results contain errors
I can't count that high :badgrin:
Fair enough.  :biggrin:
Title: Re: Sieve of Eratosthenes
Post by: daydreamer on February 24, 2025, 06:32:57 PM
Quote from: zedd151 on February 24, 2025, 07:30:26 AM
Quote from: NoCforMe on February 24, 2025, 07:29:11 AMOne might want to write #s to a file instead.
SieveOfErastothenes 1000>out.txt

'1' shouldn't be there. Yes I know it does not sound logical, given it is only divisible by itself or 1. But that's the way it is.

Prime numbers to 100 (https://www.dreambox.com/math/skills/numbers/prime-numbers#:~:text=The%20prime%20numbers%20up%20to,%2C%2083%2C%2089%2C%2097.), plus many, many other sources.
I have a primes.inc file with all primes between 0-65536 ,using DW in my 128 bit random generator thread
https://masm32.com/board/index.php?topic=7938.msg103022#msg103022
So you could include it into your program and cmp if its correct
@Steve I want to see your code ,its probably possible to port to 32 bit ,output BMP

Title: Re: Sieve of Eratosthenes
Post by: daydreamer on February 24, 2025, 06:43:20 PM
Sinsi ,nocforme
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
Look at animated gif and see in which order it multiplies to understand its mul 2,3,5,7,11,13...

Title: Re: Sieve of Eratosthenes
Post by: TimoVJL on February 24, 2025, 10:18:54 PM
The Sieve of Eratosthenes (https://wwwhomes.uni-bielefeld.de/achim/prime_sieve.html)

with example in C language.
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 12:29:31 AM
Quote from: TimoVJL on February 24, 2025, 10:18:54 PMThe Sieve of Eratosthenes
with example in C language.
Thanks Timo for you contribution. Seems to be an optimized version.  :biggrin:
Did you make any further changes to the code, or is it code directly copied from the attachment in your linked paper? Sounds like a good candidate for porting to assembly. Further enhancements/optimizations may be possible with asm.  :biggrin:  Any takers? Sinsi?  Magnus?  Jochen?  David?  Anyone?  Myself, I am busy with other projects.

"prime_sieve.c" from your attachment compiles fine with gcc. I have no experience with other compilers.
All those extraneous .pp* files are not needed.  :biggrin:

The resulting executable runs just fine.  :thumbsup:
Title: Re: Sieve of Eratosthenes
Post by: TimoVJL on February 25, 2025, 02:06:28 AM
I just made a Pelles C project for that code from that site and nothing else from me.
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 02:22:01 AM
Quote from: TimoVJL on February 25, 2025, 02:06:28 AMI just made a Pelles C project for that code from that site and nothing else from me.
Okay, thats fine. I wasn't sure, so I asked.  Nice example regardless. Thanks.  :smiley:
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 06:40:29 AM
New version. Improved sieve (mo' faster!), better formatting of output (16 numbers per line), shows correct primes (not 1!). Fully-commented, of course.
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 06:47:59 AM
Glad to have inspired you, NoCforMe. I'll take a gander at your latest Sieve of *Eratosthenes (https://en.m.wikipedia.org/wiki/Eratosthenes) code when I am back at my computer.  :smiley:

A short time later:
328 milliseconds for prime numbers to 1,000,000. Similar timings to my version posted above.
The output looks good, no apparent errors in the range 0-1,000,000.
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 07:39:09 AM
Quote from: zedd151 on February 25, 2025, 06:47:59 AM328 milliseconds for prime numbers to 1,000,000. Similar timings to my version posted above.

Does your timing include the display of those #s? or did you just time the sieve code itself?
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 07:53:13 AM
Quote from: NoCforMe on February 25, 2025, 07:39:09 AM
Quote from: zedd151 on February 25, 2025, 06:47:59 AM328 milliseconds for prime numbers to 1,000,000. Similar timings to my version posted above.

Does your timing include the display of those #s? or did you just time the sieve code itself?
The whole shebang.


start:
      invoke GetTickCount
      mov time1, eax
    CALL    WinMain
      invoke GetTickCount
      sub eax, time1
    INVOKE    StdOut, str$(eax)
    INVOKE    ExitProcess, 0

For longer, time consuming code it works okay, to test relative difference between one program or algorithm against another, or after making changes to the code to test whether the changes yields a speed improvement or not.

For much shorter pieces of code, looping multiple iterations (thousands to millions) are needed (use caution though, to not give erroneous algo results or timing errors), or other timing methods that may be more appropriate like jj's nano timer, or other methods using microsecond timers.  :smiley:

...
I had to come back and edit the code snippet to what I actually used to get the timing of your code...
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 08:31:16 AM
I'd rather see timings for just the actual sieve code.
The display code will take f-o-r-e-v-e-r.

For my program, just call Sieve() multiple times in a loop and time that whole shebang. Not hard to do.

CALL GetTickCount
MOV startTime, EAX

MOV ECX, [# times to call Sieve() ]
@@: PUSH ECX
INVOKE Sieve, maxNum, PrimeBuffer
POP ECX
LOOP @B

CALL GetTickCount
SUB EAX, startTime

; display total time in EAX
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 08:41:12 AM
4,829 milliseconds for 1000 repititions for prime numbers from 0-1000000. So 4.8 microseconds per iteration. Seems fast enough.

By the way, it registers 0 MS running the function only once.  :azn:

Here using the 'repeat' macro to run 1000 iterations of the Sieve function for the timing.
; Find those primes!

      invoke GetTickCount
      mov time1, eax
     
      repeat 1000
    INVOKE    Sieve, maxNum, PrimeBuffer
      endm
      invoke GetTickCount
      sub eax, time1
      invoke MessageBox, 0, str$(eax), 0, 0

The modified code attached, including file 'run.bat'


run.bat:
SieveOfErastothenes 1000000>out.txt

pause
I prefer using batch files than typing at the command prompt. I didn't grow up using DOS.  :biggrin:
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 10:51:11 AM
So what's the timing of your code?

BTW, you don't have to use INVOKE with GetTickCount(), since it takes no parameters. A simple CALL will do.
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 11:22:21 AM
Quote from: zedd151 on February 25, 2025, 08:41:12 AMI prefer using batch files than typing at the command prompt. I didn't grow up using DOS.  :biggrin:

Well, then you have no idea what kind of fun you missed!

But really: not trying to convince you to do something that goes against your grain, but it's actually easier in the long run having a command window open without having to continually get new ones. Of course, I use a different command processor (4DOS, been using it for decades, still works great on Windows 7) that's a bit smarter than plain old "cmd".

But the DOS commands are pretty basic and easy to remember: of course, there are your existing batch files that you simply invoke by typing their name. Then there's COPY, DEL, etc. for files. And the command window keeps a history of previous commands executed, so you can look back and see which assembler errors are still there, f'rinstance.

Even "cmd" has a HELP command.

You might try it some day when you have time and maybe are really bored ...
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 11:22:35 AM
Quote from: NoCforMe on February 25, 2025, 10:51:11 AMSo what's the timing of your code?
It took me a minute to procedurize that part of the code....

11,487 milliseconds for 1,000 iterations for primes 0-1,000,000... Yikes! almost takes three times longer than your latest. :rolleyes:

Bbbutt, bbbut, but wait a minute. I thought you didn't give two hoots how fast code is, or could be...  :greensml:

QuoteBTW, you don't have to use INVOKE with GetTickCount(), since it takes no parameters. A simple CALL will do.
it's muscle memory that forces me to always write 'invoke'. That's my story and I'm sticking to it.  :biggrin:

I 'invoke' and 'call' --- ALL CAPS IS SO 1980's...


... I had some weird formatting bugs when posting originally. I musta accidentally hit some formatting buttons...
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 11:26:42 AM
Quote from: zedd151 on February 25, 2025, 11:22:35 AMI 'invoke' and 'call' --- ALL CAPS IS SO 1980's...

Ackshooly, it's more like 1960s. Like those programs that ran the Apollo mission.
Title: Re: Sieve of Eratosthenes
Post by: NoCforMe on February 25, 2025, 11:58:31 AM
Quote from: zedd151 on February 25, 2025, 11:22:35 AM11,487 milliseconds for 1,000 iterations for primes 0-1,000,000... Yikes! almost takes three times longer than your latest. :rolleyes:

Bbbutt, bbbut, but wait a minute. I thought you didn't give two hoots how fast code is, or could be...  :greensml:

Normally I don't. But in this case I get to say:

Nya nya nya nya: My code's faster than your code!

(If you care, you need to skip computing multiples of numbers that are already taken out as primes, as sinsi suggested upthread. Then yours will be as fast as mine.)
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 12:26:13 PM
Quote from: NoCforMe on February 25, 2025, 11:58:31 AM
Quote from: zedd151 on February 25, 2025, 11:22:35 AMBbbutt, bbbut, but wait a minute. I thought you didn't give two hoots how fast code is, or could be...  :greensml:
Normally I don't. But in this case I get to say:

Nya nya nya nya: My code's faster than your code!

When I wrote that code, I was more concerned about accuracy and simplicity than speed. If you give me a coupla days, I'll make mine faster than yours.  :badgrin:

Just kidding, mine still serves a purpose, as is.
Title: Re: Sieve of Eratosthenes
Post by: ognil on February 25, 2025, 01:06:44 PM
Just my five cents :smiley:

; Sieve of Eratosthenes in MASM64

include  \masm64\include64\masm64rt.inc

.data
    n      dq 1000000               ; Limit for prime numbers
    sqrt_n dq 3e8h                  ; Square root of n
    sieve  db 1000000 dup(1)        ; Sieve array, initialized to 1 (true)

.code
align 16
db  3 dup(90h)
entry_point proc
; Calculate sqrt(n)
   ; fild n
   ; fsqrt
   ; fistp sqrt_n

; Initialize  registers
    mov     rdx, 2                  ; Start from the first prime number
    lea     r8,  sieve
    mov     r9,  n                  ; r9 = Limit for prime numbers
@loop:
    cmp     byte ptr [r8+rdx],1     ; Check if sieve[rdx] is 1 (true)
    mov     rax, rdx
    jne     @next
    nop
    imul    rax, rax
    nop
@@:
    mov     byte ptr [r8+rax], 0    ; Mark multiples of rax as 0 (false) Set sieve[rax] to 0
    add     rax, rdx
    cmp     rax, r9                 ; r9 = Limit for prime numbers
    jb      @b
@next:
    add     rdx, 1
    cmp     rdx, 3e8h               ; sqrt_n = 3e8h
    jbe     @loop
    xor     rcx, rcx
    call    ExitProcess             ; Exit the program
entry_point endp

end
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 04:23:20 PM
Quote from: ognil on February 25, 2025, 01:06:44 PMJust my five cents :smiley:
:biggrin:
32 bit conversion below. I hope that you don't mind.
After a couple changes, the prime listing is 100% accurate.  :thumbsup:
Title: Re: Sieve of Eratosthenes
Post by: zedd151 on February 25, 2025, 04:39:36 PM
I have converted ognils 64 bit code to 32 bit.
And I made a change by preinitialising the .data section array so all even numbers are pre-initialized to zero, and marked 1 as non prime, and 2 as prime manually in the code..

Added function to print the prime numbers. Use Console Assemble & Link.

; Sieve of Eratosthenes - ognil
; 32 bit conversion by zedd151 - also added code to print results, and a couple other adjustments

include  \masm32\include\masm32rt.inc

.data
    n       dd 1000000               ; Limit for prime numbers
    sqrt_n  dd 1000                  ; Square root of n

      ; array is now 250000 dwords, but will use it bytewise.
      ; we mark initialize all even numbers to zero.
     
    sieve   dd 250000 dup(01000100h)  ; Sieve array, initialized to 00, 01, 00, 01, etc.
    time1   dd 0
.code

PrimeSieve proc
    push ebx
    push edi
    xor edx, edx                     ; set edx to 2
    inc edx                          ; doing it this way aligns both loops to 4
    inc edx                          ; Start from the first prime number
    lea     edi,  sieve
    mov     byte ptr [edi+1], 0      ; mark 1 as not prime
    mov     byte ptr [edi+2], 1      ; mark 2 as prime
    mov     ebx,  n                  ; ebx = Limit for prime numbers
    nop                              ; padding to align loops to 4 bytes
    nop
@loop:
    cmp     byte ptr [edi+edx],1     ; Check if sieve[edx] is 1 (true)
    mov     eax, edx
    jne     @next
    nop
    imul    eax, eax
@@:
    mov     byte ptr [edi+eax], 0    ; Mark multiples of eax as 0 (false) Set sieve[eax] to 0
    add     eax, edx
    cmp     eax, ebx                 ; ebx = Limit for prime numbers
    jb      @b
@next:
    add     edx, 1
    cmp     edx, 3e8h                ; sqrt_n = 3e8h
    jbe     @loop
    pop edi
    pop ebx
    ret
PrimeSieve endp

PrintPrimes proc
    push ebx
    push edi
    lea edi, sieve
    xor ebx, ebx
  @@:
    cmp byte ptr [edi+ebx], 0
    jz noprint
    print str$(ebx), 13, 10
  noprint:
    inc ebx
    cmp ebx, n
    jnz @b
    pop edi
    pop ebx
    ret
PrintPrimes endp

start:
 
    CALL PrimeSieve                  ; just for NoCforMe!
    call PrintPrimes                 ;  :)
    push 0
    call    ExitProcess              ; Exit the program

end start

1219 milliseconds for 1000 iterations for range 0-1000000

1.2 microseconds to get primes from 0-1000000. Very fast indeed.