class EasterVariable extends AbstractSingleTsVariable implements IEasterVariable {

    @Override
    public void data(TsPeriod start, DataBlock data) {
        data.set(0);
        int freq = start.getFrequency().intValue();
        if ((freq != 12 && freq != 4) || dur_ < 1 || dur_ > 25) {
            return;
        }
        int n = data.getLength();
        int c = 12 / freq;
        int y0 = start.getYear();
        int p0 = start.getPosition() * c;
        if (p0 > 3) {
            p0 -= 12;
            ++y0;
        }
        // first april
        int idx = (3 - p0) / c;
        if (idx > n) {
            return;
        }

        double dur = dur_;


        GregorianCalendar easter = new GregorianCalendar();
        for (int y = y0; idx <= n; ++y, idx += freq) {
            easter.setTime(Utilities.easter(y).getTime());
            // DAY_OF_MONTH is 1-based
            int day = easter.get(GregorianCalendar.DAY_OF_MONTH);
            int month = easter.get(GregorianCalendar.MONTH);
            if (!m_e) {
                --day;
            } else if (m_m) {
                if (day == 31) {
                    day = 1;
                    ++month;
                } else {
                    ++day;
                }
            }

            // MONTH is 0-based
            double m = 0, a = 0;
            if (type_ == Correction.Simple) {
                if (month == 2 || day == 0) {
                    m = .5;
                    a = -.5;
                } else if (day >= dur_) {
                    m = -.5;
                    a = .5;
                } else {
                    m = (dur - day) / dur - .5;
                    a = -m;
                }
            } else // use long mean correction. Mean correction should be adapted
            // to take into account the new solution proposed in tramo (easter, easter monday)
            // included in the holiday
            {
                double m_av = 0, a_av = 0;
                if (type_ == Correction.PreComputed) {
                    m_av = EMeans_Mar[25 - dur_]; //(21 + dur) / 70.0;
                    a_av = EMeans_Apr[25 - dur_];//(49 - dur) / 70.0;
                } else {
                    /*
                     * Raw estimation of the probability to get Easter at a specific date is defined below:
                     * 22/3 (1/7)*1/LUNARY
                     * 23/3 (2/7)*1/LUNARY
                     * ...
                     * 27/3 (6/7)*1/LUNARY
                     * 28/3 1/LUNARY
                     * ...
                     * 18/4 1/LUNARY
                     * 19/4 1/LUNARY + (1/7) * DEC_LUNARY/LUNARY = (7 + DEC_LUNARY)/(7 * LUNARY)
                     * 20/4 (6/7)*1/LUNARY + (1/7) * DEC_LUNARY/LUNARY = (6 + DEC_LUNARY)/(7 * LUNARY)
                     * 21/4 (5/7)*1/LUNARY + (1/7) * DEC_LUNARY/LUNARY
                     * 22/4 (4/7)*1/LUNARY + (1/7) * DEC_LUNARY/LUNARY
                     * 23/4 (3/7)*1/LUNARY + (1/7) * DEC_LUNARY/LUNARY
                     * 24/4 (2/7)*1/LUNARY + (1/7) * DEC_LUNARY/LUNARY
                     * 25/4 (1/7)*1/LUNARY + (1/7) * DEC_LUNARY/LUNARY
                     * 
                     * In comparison with long term (5700000 years) computations based on several algorithms,
                     * the error is small (< 0.0025)
                     * 
                     * The average number in march, folliwng dur (<= 15 !!!) is computed as follow:
                     * + for period 22/3 to 27/3: always in march
                     *    dur * (1/7 + ... + 6/7)/LUNARY = dur * 3 / LUNARY 
                     * + for period 28/3 to 1/4: always in march
                     *    dur * 5 / LUNARY
                     * + for period 2/4 to dur/4
                     *    (dur-1 + dur-2 + 1) / LUNARY = dur * (dur-1) / (2 * LUNARY)
                     * + for other dates: 0
                     * 
                     * Total:
                     *   dur * (6+10+dur-1)/ (2* LUNARY) = dur * 15 / (2 * LUNARY)
                     * Relative part:
                     *   15 / (2* LUNARY)
                     */
                    m_av = (15 + dur) / (2 * Utilities.LUNARY);
                    a_av = 1 - m_av;
                }
                if (month == 2) {
                    m = 1 - m_av;
                    a = -a_av;
                } else if (day >= dur_) {
                    m = -m_av;
                    a = 1 - a_av;
                } else {
                    m = (dur - day) / dur - m_av;
                    a = day / dur - a_av;
                }
            }

            if (idx - 1 >= 0) {
                data.set(idx - 1, m);
            }
            if (idx < n) {
                data.set(idx, a);
            }
        }
    }

    public  EasterVariable();

}