К оглавлению

Порядки и порядки Фробениуса чисел по простому модулю

С.И.Хашин

Обычные порядки:
orders.h - заголовочный файл
orders.cpp - реализация.

Порядки Фробениуса:
forders.h - заголовочный файл
forders.cpp - реализация.


Вычисление, сохранение в файл, последующее чтение и быстрый доступ к порядкам целого a по различным простым модулям p, начиная с 2 и до заданного предела.

Нахождение порядка числа a по простому модулю p — довольно медленная процедура. Требуется во-первых, разложить число p-1 на простые множители, а во-вторых много раз вычислять ak mod p для различных k. Поэтому желательно иметь заранее вычисленные значения порядков.

Для реализации этого предлагается класс orders и несколько статических его членов (динамических членов у класса нет). Модуль состоит из двух файлов:

orders.h - заголовочный файл
orders.cpp - реализация.

Класс используется совместно с модулем z64 и является его продолжением.

Основные методы класса:

    static int  fill(unsigned a0, u64 maxN=0);  // load/calculate seive and orders(base)

При первом запуске вычисляет искомые порядки, то есть порядки числа a по всем простым модулям, меньшим maxN. Эти порядки запоминаются в файле и при следующем запуске уже не вычисляются, а просто загружаются из файла.

Имя файла задается в функции

    static char *order_file_name( unsigned a0);
и сейчас оно выглядит так:
    sprintf(fname_buf, "%sords\\ord_%04d.dat", z64::path, a0);
где z64::path — путь к файлу, из которого загружались простые числа в модуле z64.
    static unsigned nOrd();                 // number of calculated orders
    static u64      maxP();                 // last P
    static unsigned A()   ;                 // base
    static u64      ordI(unsigned i);       // order(a, p(i))
    static u64      ordP(u64 p0);           // order(a, p0)
    static u64      ordPP(u64 p0, int k);   // order(a, p0^k)
    static u64      ordN(u64 n);            // order(a, n), n - any natural
    static u64      iordP(u64 p0);          // (p0-1)/order(a, p0)

Я на своем компьютере за несколько часов создал в каталоге C:\a\primes\ords\ файлы ord_NNNN.dat, где NNNN – все простые числа от 2 до 257, то есть файлы

ord_0002.dat
ord_0003.dat
...
ord_0257.dat

Пример использования:

    u64 maxN = 1 << 30;                     // 2^30
    Eload(maxN);                            // Читаем список простых чисел до maxN
    int a = 11;                             // База
    orders::fill(a, maxN);                  // Читаем порядки числа a по модулям простых чисел до maxN
    double sum = 0, summ = 0;
    for (u64 p = z64::NextPrime(a); p < maxN; p = z64::NextPrime(p)) {
        u64 iq = orders::iordP(p);
        sum += iq;
        summ += 1./iq;
        cnt++;
    }
    printf("%3d, %15.10f, %15.10f\n", a, sum/cnt, summ/cnt);

Для вычисления порядков Фробениуса используется аналогичный модуль forders. Вот его основные функции:

    static int  fill(int a0, int b0, int c0, u64 maxN=0);   // load/calculate seive and orders(base)
    static unsigned nOrd() {return nord; };     // number of calculated orders
    static u64      maxP() {return maxP_; };    // last P
    static int      A()    {return a; };        // base
    static int      B()    {return b; };        // base
    static int      C()    {return c; };        // base
    static u64      fordI(unsigned i);          // FrobOrder(a,b,c, p(i))
    static u64      fordP(u64 p0);              // FrobOrder(a,b,c, p0)
    static unsigned fCordI(unsigned i);         // co-FrobOrder(a,b,c, p(i))
    static u64      fCordP(u64 p0);             // co-FrobOrder(a,b,c, p0)

Замечание. Если число a является квадратичным вычетом по модулю p (то есть является полным квадратом по модулю p), то порядок Фробениуса считаем равным 0!

Пример использования:

    u64 maxN = 1 << 30;                     // 2^30
    Eload(maxN);                            // Читаем список простых чисел до maxN
    int a = 11;                             // База
    orders::fill(a, maxN);                  // Читаем порядки Фробениуса числа a по модулям простых чисел до maxN
    double sum = 0, summ = 0;
    for (u64 p = z64::NextPrime(a); p < maxN; p = z64::NextPrime(p)) {
        u64 iq = forders::fordP(p);
        sum += iq;
        summ += 1./iq;
        cnt++;
    }
    printf("%3d, %15.10f, %15.10f\n", a, sum/cnt, summ/cnt);

К оглавлению


free counters