February 24

Merhaba,

Bir süredir, (std.bitmanip.BitArray ile) true/false olarak depolanan veriyi baştan sona hesaplatırken belli bir aralığı hesaplatabilir miyim diye düşünüyorum; uzun zaman aldığı için...

Gerçi eski koda göre dakikaları bulan (250 milyon veri: 250002752 bits)'lik veriyi 10 sn. altına indirmeyi başardım. Kodu, bir aralık ile vakti geldikçe paylaşacağım. Örnek aldığım konu bir akademisyenin yaptığı (Jabari Zakiya, ref.PGT) ve Goldbach'ın varsayımına dayanan şu koda göre olacak: https://forum.dlang.org/thread/zofrzdagqofkntcubhvm@forum.dlang.org (3. sayfa ve sonrasına bakın...)

Son bir şey: AI ile bir temel attım. Yani thinking'i kullanarak pat diye sordum ve onlar (DeepSeek ve Grok3) epey düşünerek cevapladılar ama hala kafamda oturmayan şeyler var. Cevap yazmasanız da olur ama izleyici olarak kalmayıp guncuklayın çünkü çok eğlenceli/eğitici olabilir!

Öncelikle konu aldığım kodu (prime_pairs_lohi() işlevini) yönetilebilir kılmak için parçalara böldüm ve sort!"a < b" ile setDifference() işlemlerinden yalıttım. Bunun için BitArray kullandım. Gerçi sıralamadan vazgeçmem RandomRange'e işaret ediyor. İşte yontulması gereken püf nokta tam olarak bura sanırım!

Bir sarma (BitBuffer) ile kod şöyle çalışıyor:

//import std.array, std.algorithm, std.range;
import std.stdio;
import std.datetime.stopwatch : StopWatch;

void main()
{
  alias Type = ulong;
  enum n = Type(500_005_446);

  auto timer = StopWatch();
       timer.start();

  // Initialize Buffer
  auto buff = BitBuffer!Type(3, n / 2);

  // Set double digits
  buff.data[0..$] = 0xAAAAAAAAAAAAAAAA;
  buff.buffer[1] = false; /* or
  buff.data[0] -= 2;//* 1010 -> 1100 */

  // Step 1
  buff.gcdFilter!Type(n);

  // Step 2
  buff.mulFilter!Type(n);

  auto lhr = buff.array;
  writeln([n,       lhr.length]); // show n and pcp prime pairs count
  writeln([lhr[0],    n-lhr[0]]); // show first pcp prime pair of n
  writeln([lhr[$-1],n-lhr[$-1]]); // show last  pcp prime pair of n
  timer.peek.writeln();
}

Görüldüğü gibi karmaşık kurulum işlemlerini saymazsak temelde 2 işlem (ilk çok basit) var. Hatta GCD ile filtrelemeyi ve sonuç göstermeyi de yok varsayın lütfen. O yüzden yoğunlaşmamız gereken işlev/aşama buff.mulFilter!Type(n); // Step 2 olacak:

void mulFilter(T)(BitBuffer!T buff, T n)
{
    const T ndiv2 = n >> 1;
    const T rhi = n - 2;

    auto lhr = buff.array;
    foreach (i, r; lhr)
    {
        const T rMax = rhi / r;
        if (r <= rMax)
        {
            const T r2 = r * r;
            if (const T value = (r2 < ndiv2) ? r2 : n - r2)
            {
                buff.buffer[value] = false;
            }

            foreach (ri; lhr[i + 1 .. $])
            {
                if (ri > rMax) break;

                const T r1 = r * ri;
                if (const T value = (r1 < ndiv2) ? r1 : n - r1)
                {
                    buff.buffer[value] = false;
                }
            }
        }
    }
}

Aslında kendi sarmamda kendi array metodunu icra ettim. Yani kolaya kaçtım; RandomRange'e basit bir şekilde erişmek için. Yine çıktıyı dert etmeyin. Çünkü BitArray'de aralık döndüren bitsSet var. Görüldüğü gibi kod çok basit ve geride asal çiftleri bırakıyor. Yani her bir sayı n'den çıkarıldığında yine bir asal sayı oluyor.

Bu kısa özetten sonra yontulması gereken o tırtıklı yüzeye geliyoruz:

RandomRange'e gerçekten ihtiyacımız var mı?

Yani kodun çekirdeğindeki bu işlevi (mulFilter) belli bir aralık için (örn. ilk 100'e) uygulayıp sonsuz bir aralık üzerinde koşturabilir miyiz? Daha da güzel bir soru:

Başlangıçta kurulan lineer buffer'ı, circular buffer'a çevirebilir miyiz?

Yani sonuçta neden 250 milyon bitlik bir buffer'a ile belleği israf edelim ki! İhtiyacımız olan kısım hesaplandıkça buffer ileriye doğru (sonuçta her sayı 1 ve 0) kayabilir. Önemli olan başlangıç değeridir ve BigInt kullanılabilir.

Alın bir de burdan yakın :)

SDB@79

6 days ago
On 2/23/25 6:45 PM, Salih Dincer wrote:

> RandomRange'e gerçekten ihtiyacımız var mı?

Yalnızca koda bakarak, [value] dendiğine göre, evet, var. Ama:

> Örnek aldığım konu bir akademisyenin
> yaptığı

Akademisyen olmadığım için bu konu için RandomRange kullanmayan algoritma olup olmadığını bilemem. :)

> Başlangıçta kurulan lineer buffer'ı, circular buffer'a çevirebilir miyiz?

Bilmiyorum ama bu soru bana daha önce yazdığım şu modülleri hatırlattı:

  https://github.com/acehreli/alid

Orada güzel şeyler olduğunu hatırlıyordum ama şimdi bakınca kendi yazdığıma inanamıyorum. :)

Acaba oradaki circularblock senin de işine yarar mı?

Ali