Joost Behrends wrote:
apfelmus writes:

Huh? p < intsqrt n is evaluated just as often as p*p > n , with changing n . Why would that be less expensive? Btw, the code above test for r==0 first, which means that the following p*p > n is tested exactly once for every prime candidate p .

No. One point in the introduction of DivIter is, that intsqrt dividend is stored
there and only recomputed, when a new factor is found.

Yes, I'm sorry, it didn't occur to me that recomputing per actual prime factor (with multiplicities, i.e. p^5 counted 5 times) is better than recomputing per candidate factor (without multiplicities, i.e. p^5 counted only once).

And concerning my cycled lists of summands as [2,4] or [2,4,2,4,2,4,2,6,2,6]:

an easily computable function stepping through all primes can only be
a function, which yields primes plus some more odd numbers. This is, what i
tried.

Yes, this scheme was my intention, too. The list primes' doesn't need to (and indeed shouldn't) be a list of actual primes, just a good guess like

  primes' = 2:[3,5]
  primes' = 2:3:scanl (+) 5 (cycle [2,4])

or something with [2,4,2,4,2,4,2,6,2,6]. So, it's an infinite list of numbers that qualify as candidates for being a prime factor of n (which I called "prime candidates". Not a good name, since they don't need to be actual prime numbers.)


What I want to say is that using such an infinite is a nice way to separate the generate-prime-factor-candidates-logic from the test-all-those-candidates-loop. It's not necessary to hard-code it with a predicate like

iterdivisors x | x == 0 = 3
               | x == 1 = 5
               | otherwise x = iterdivisors (x-1) + ((cycle [2,4]) !! x)

(which, in this particular form, is hopelessly inefficient) or special step functions like

d2 :: DivIter                         -> DivIter
d2 x |dividend x `mod` divisor x > 0  = x { divisor = divisor x + 2}
     |otherwise                       = found x
d4 :: DivIter                         -> DivIter
d4 x |dividend x `mod` divisor x > 0  = x { divisor = divisor x + 4}
     |otherwise                       = found x
d6 :: DivIter                         -> DivIter
d6 x |dividend x `mod` divisor x > 0  = x { divisor = divisor x + 6}
     |otherwise                       = found x

divisions :: DivIter             -> DivIter
divisions y |or[divisor y == 3, divisor y == 5] = divisions (d2 y)
            |divisor y <= bound y = divisions (d6$d2$d6$d4$d2$d4$d2$d4 y)
            |otherwise            = y

It's not even necessary to treat 2 in a special way like

twosect :: (Integer,[Integer]) -> (Integer,[Integer])
twosect m |odd  (fst m) = m
          |even (fst m) = twosect (div (fst m) 2, snd m ++ [2])

does, the  primes'  list handles it all.


Regards
apfelmus

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to