Download cpp source code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <QtMath>
#include <QVector>

#include "GoldbachWorker.h"

GoldbachWorker::GoldbachWorker(long long number, int workerId, int workerCount, QVector<QString>& results, QObject *parent)
    : QThread{parent}
    , number{number}
    , workerId{workerId}
    , workerCount{workerCount}
    , results{results}
{
}

void GoldbachWorker::run()
{
    long long sumCount = this->calculate(this->number);
    emit calculationDone(sumCount);
}

long long GoldbachWorker::calculateStart(long long dataCount, int workerCount, int workerId, long long dataStart)
{
    Q_ASSERT(dataStart < dataCount);
    const long long equitative = workerId * ((dataCount - dataStart) / workerCount);
    const long long overload = qMin(static_cast<long long>(workerId), (dataCount - dataStart) % workerCount);
    return dataStart + equitative + overload;
}

long long GoldbachWorker::calculateFinish(long long dataCount, int workerCount, int workerId, long long dataStart)
{
    return calculateStart(dataCount, workerCount, workerId + 1, dataStart);
}

void GoldbachWorker::updateProgress(int newPercent)
{
    if ( this->progressPercent != newPercent )
    {
        this->progressPercent = newPercent;
        emit this->progressUpdated( this->workerId, this->progressPercent );
    }
}

long long GoldbachWorker::calculate(long long number)
{
    if ( number < 4 || number == 5 ) return 0;
    this->progressPercent = 0;
    return number % 2 == 0 ? calculateEvenGoldbach(number) : calculateOddGoldbach(number);
}

//#include <iostream>
long long GoldbachWorker::calculateEvenGoldbach(long long number)
{
    long long resultCount = 0;
    long long start  = calculateStart (number, this->workerCount, this->workerId, 2);
    long long finish = calculateFinish(number, this->workerCount, this->workerId, 2);
//    std::cout << this->workerId << ": [" << start << ", " << finish << "[" << std::endl;

    for ( long long a = start; a < finish && this->isInterruptionRequested() == false; ++a )
    {
        this->updateProgress(static_cast<int>(100LL * (a - start + 1) / (finish - start)));

        if ( ! isPrime(a) ) continue;
        long long b = number - a;
        if ( b >= a && isPrime(b) )
        {
            this->results.append( tr("%1 + %2").arg(a).arg(b) );
            ++resultCount;
        }
    }
    return resultCount;
}

long long GoldbachWorker::calculateOddGoldbach(long long number)
{
    long long resultCount = 0;
    long long start  = calculateStart (number, this->workerCount, this->workerId, 2);
    long long finish = calculateFinish(number, this->workerCount, this->workerId, 2);
//    std::cout << this->workerId << ": [" << start << ", " << finish << "[" << std::endl;

    for ( long long a = start; a < finish; ++a )
    {
        this->updateProgress( static_cast<int>(100LL * (a - start + 1) / (finish - start)) );

        if ( ! isPrime(a) ) continue;
        for ( long long b = a; b < number; ++b )
        {
            if ( this->isInterruptionRequested() )
                return resultCount;

            if ( ! isPrime(b) ) continue;
            long long c = number - a - b;
            if ( c >= b && isPrime(c) )
            {
                this->results.append( tr("%1 + %2 + %3").arg(a).arg(b).arg(c) );
                ++resultCount;
            }
        }
    }
    return resultCount;
}

bool GoldbachWorker::isPrime(long long number)
{
    if ( number < 2 ) return false;

    long long last = static_cast<long long>( qSqrt( number) );
    for ( long long i = 2; i <= last; ++i )
        if ( number % i == 0 )
            return false;

    return true;
}