comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: All day FFT....
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Return to the default flat view Create a new topic Submit Reply
prime factors (was Re: All day FFT....) [message #29235 is a reply to message #29208] Fri, 08 February 2002 12:47 Go to previous message
Brian Jackel is currently offline  Brian Jackel
Messages: 34
Registered: January 1998
Member
Hi Bob, Martin

Here's my contribution to the prime number wars.
Not recursive, I'm afraid.

A single benchmarks shows it as being 10% faster
than Martin's code. Your mileage may vary.

IDL> num= 124123L*7L*3L*5L & st= systime(1) & for indx=0,9999 do dummy=
ifactors(num) & print,systime(1)-st
6.6720001
IDL> num= 124123L*7L*3L*5L & st= systime(1) & for indx=0,9999 do dummy=
prime_factors(num) & print,systime(1)-st
5.5940000


;All bug reports cheerfully accepted

;Brian Jackel

;bjackel@phys.ucalgary.ca

;+

; NAME: Prime_Factors

;

; PURPOSE: This function accepts a single (scalar) value, and returns a

; vector containing all the prime factors of that value. This
is

; useful for seeing if FFT's will be fast, or reducing
fractions.

;

; CATEGORY: Math

;

; CALLING SEQUENCE: Result= PRIME_FACTORS(Value)

;

; INPUTS: Value a scalar byte, integer, or long integer value.

;

; KEYWORDS: SORT if set, then the result will be sorted in increasing

; order. Otherwise, factors may be scattered in no

; particular order.

;

; UNIQUE if set, then the result will only contain one of each

; factor ie. multiple occurances will be removed. This

; is done using the library function UNIQ. Note that

; this requires SORTing.

;

; OUTPUTS: The result of this function will be a vector containing all

; prime factors of the input value. If the input value is

; prime, then the result will have only one element, equal

; to the input.

;

; RESTRICTIONS: Fastest if no prime factor is greater than 97, quite
slow

; after that, approximately order(sqrt(N)), where N is the

; largest prime factor.

;

; Only works for positive numbers.

;

; PROCEDURE: Do a fast search for all primes up to 97, then slowly loop

; through the rest (if any).

;

; EXAMPLES:

;

;IDL> test=PRIME_FACTORS(1L) & PRINT,test

; 1

;

;IDL> test=PRIME_FACTORS(5414145L) & PRINT,test

; 3 5 11 19 11 157

;

;IDL> test=PRIME_FACTORS(5414147L) & PRINT,test

; 5414147

;

; MODIFICATION HISTORY:

; Written February 14 1995, Brian Jackel, University of Western Ontario

; September 3 1995 Bjj Increased the list of primes to 97, improved
the dumb

; loop considerably: O(n) to O(sqrt(n)/2)

; Screened input better, added /SORT and /UNIQUE

;-





FUNCTION PRIME_FACTORS,value,SORT=sort,UNIQUE=unique



IF (N_PARAMS() LT 1) THEN MESSAGE,"Error- this function requires a
scalar input parameter"

IF (N_ELEMENTS(value) GT 1) THEN MESSAGE,"Error- this function only
accepts scalar input"

IF (value EQ 0) THEN BEGIN

MESSAGE,'Warning- input value was zero ',/INFORMATIONAL

RETURN,[0L]

ENDIF

IF (value LT 0) THEN MESSAGE,'Warning- input value was
negative',/INFORMATIONAL



IF ((value - LONG(value)) NE 0) THEN BEGIN

MESSAGE,"Warning- Value should be an integer, but is
"+STRING(value),/INFORMATIONAL

RETURN,[1L]

ENDIF



work= ABS(value) ;make a working copy

factors= value/work ;1 (or maybe -1) is always a factor, albeit a
trivial one



;

;For this first bit we just have a list of prime numbers (up to 97),

;and check if "work" is divisible by any of them. If so, make a note

;of it, and divide "work" by the appropriate factors. Repeat until

;"work" is no longer divisible by anything in the list. This either

;means that we've got all the factors, or the remaining ones are

;larger than 97.

;

some_primes=
[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]



REPEAT BEGIN

w= WHERE( (work MOD some_primes) EQ 0 ,nw ) ;see if any
thing in the list matches

IF (nw GT 0) THEN BEGIN

some_primes= some_primes(w) ;throw away
everything but the prime factors

factors= [factors,some_primes]

temp= some_primes(0)

FOR indx=1,nw-1 DO temp=temp*some_primes(indx)

work= work/temp ;divide the
working value by all prime factors

ENDIF

ENDREP UNTIL (nw EQ 0)



;

;At this point we've found all the prime factors up til 97.

;Not having any better idea, I'll just keep trying to divide "work"

;by larger and larger numbers, until I've removed all the factors,

;or the Universe ends.

;

;Really, we should only be trying to divide by prime numbers, but if

;I had a quick way to test the primeness of numbers I'd be rich and

;famous by now.

;

;Note, however, that even numbers aren't prime, so we can halve the

;search space by concentrating only on odd numbers. We really should

;also ignore anything that ends in 5, but that actually slows things

;down a bit. Ideally we would use a base 6 number system, which would

;allow us to ignore 2/3 of the numbers instead of 1/2 or 6/10.

;

;Also, we can only have to search up to SQRT(work), which changes the

;time from O(n) to O(sqrt(n)), a significant improvement.



upper_limit= FIX( SQRT(work) + 1 ) ;highest number to check, about
SQRT(2^31)=45000, so worst case should still be pretty fast

current_try= 101L

WHILE (current_try LT upper_limit) DO BEGIN



IF ((work MOD current_try) EQ 0) THEN BEGIN

nfactors= 0

REPEAT BEGIN

work= work / current_try

nfactors= nfactors+1

ENDREP UNTIL (work MOD current_try) NE 0

factors= [factors, REPLICATE(current_try,nfactors)]

upper_limit= FIX( SQRT(work) + 1 )

ENDIF



current_try= current_try + 2L



ENDWHILE



;At this point, if "work" isn't 1, then it must be prime.

;Also, throw away the first element in "factors" (was a

; dummy 1) unless the input value was simply 1.

;

IF (work NE 1) THEN factors= [factors,work] ;anything left at this
point must be a prime

IF (value NE 1) THEN factors= factors(1:*)





IF KEYWORD_SET(SORT) OR KEYWORD_SET(UNIQUE) THEN factors= factors(
SORT(factors) )

IF KEYWORD_SET(UNIQUE) THEN factors= factors( UNIQ(factors) )





RETURN,factors

END
[Message index]
 
Read Message
Read Message
Read Message
Previous Topic: Re: Variables in SAVE files
Next Topic: log scale of data coloring of IDLgrVolume object, not the axes

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 19:27:13 PDT 2025

Total time taken to generate the page: 0.00178 seconds