Re: Generators 2 в избранное  новое всё   подписка   модер. 
От: R.K. 
Дата: 29.05.08 15:35
Оценка:33 (3)
Здравствуйте, remark, Вы писали:

R>Немного пропатчил версию c-smile:

R>http://www.rsdn.ru/forum/message/2965247.1.aspx
Автор: c-smile
Дата: 27.05.08


Если поменять еще немного, можно организовать взаимнорекурсивные генераторы
// ...
#define generator(NAME, T, NAME_T) class NAME : public generator_base<NAME_T, T>
// ...


То, что я хочу переписать на с++: Re[22]: Write in Nemerle!
Автор: R.K.
Дата: 04.12.06
(и дальше по теме)...

#include <vector>
#include <deque>
#include <math.h>
#include <time.h>
#include "../generator.h"

template <typename Primes>
generator(gen_map, unsigned, gen_map<Primes>)
{
    const unsigned p0_, p1_, lo_, hi_, bound_;
    std::vector<bool> arr_;
    unsigned i_, n_;

    static unsigned correct(unsigned n, unsigned i)
    { return n & 1 ? n : n + i; }

public:
    gen_map(unsigned p0, unsigned p1)
        : p0_(p0), p1_(p1)
        , lo_(p0 * p0), hi_(p1 * p1)
        , bound_((hi_ - lo_) / 2 - 1)
        , arr_(bound_ + 1, true)
    {
        Primes ps(3);
        for (ps.next(); ps.value() < p1_; ps.next())
        {
            const unsigned i = ps.value();
            for (unsigned j = (correct(lo_ - lo_ % i + i, i) - lo_) / 2
                ; j <= bound_
                ; j += i)
                arr_[j] = false;
        }
    }

    emit(unsigned)
    {
        for (i_ = 1, n_ = lo_ + 2; i_ <= bound_; ++i_, n_ += 2)
        {
            if (!arr_[i_])
                continue;
            yield(n_);
        }
    }
    stop_emit()
};

inline unsigned sqrt_int(unsigned x)
{ return static_cast<unsigned>(sqrt(static_cast<double>(x))); }

generator(primes, unsigned, primes)
{
    const unsigned n_, sq_n_;
    gen_map<primes> *gmap_;
    unsigned p0_, p1_, i_;
    primes *ps_;

    void dispose()
    {
        if (gmap_)
            delete gmap_;
        gmap_ = 0;
    }

public:
    primes(unsigned n = 2)
        : n_(n)
        , sq_n_(sqrt_int(n))
        , gmap_(0)
        , ps_(0)
    {
    }

    ~primes()
    {
        dispose();
        if (ps_)
            delete ps_;
    }

    emit(unsigned)
    {
        if (n_ <= 2) yield(2);
        if (n_ <= 3) yield(3);
        if (n_ <= 5) yield(5);
        if (n_ <= 7) yield(7);
        ps_ = new primes(3);
        ps_->next();
        p1_ = ps_->value();
        for (;;)
        {
            p0_ = p1_;
            ps_->next();
            p1_ = ps_->value();
            if (p1_ <= sq_n_)
                continue;
            dispose();
            gmap_ = new gen_map<primes>(p0_, p1_);
            while (gmap_->next())
                if (gmap_->value() >= n_)
                    yield(gmap_->value());
        }
    }
    stop_emit()
};

int main()
{
    primes ps(100000000);
    int sum = 0;
    long tim0 = clock();
    for (ps.next(); ps.value() <= 120000000; ps.next(), ++sum);
    printf("sum = %d, time: %g sec.\n", sum, (clock() - tim0) / 1000.0);
}
You aren't expected to absorb this