static class Astro {
    double jd;      /* Astronomical Julian day (for local time with Delta-t) */
    double[] dec = new double[3];  /* Declination */
    double[] ra = new double[3];   /* Right Ascensions */
    double[] sid = new double[3];  /* Apparent sidereal time */
    double[] dra = new double[3];  /* Delta Right Ascensions */
    double[] rsum = new double[3]; /* Sum of periodic values for radius vector R */

    Astro() {
    }

    Astro(Astro src) {
        this.jd = src.jd;
        this.dec = src.dec;
        this.ra = src.ra;
        this.sid = src.sid;
        this.dra = src.dra;
        this.rsum = src.rsum;
    }
} static final double DEG_TO_10_BASE = 1 / 15.0; static double DEG_TO_RAD(double A) {
    return ((A) * (PI / 180.0));
} static final int INVALID_TRIGGER = 1; static double RAD_TO_DEG(double A) {
    return ((A) / (PI / 180.0));
} static void getAstroValuesByDay(double julianDay, Location loc, Astro astro,
                                Astro topAstro) {
    final AstroDay ad = new AstroDay();

    if (astro.jd == julianDay - 1) {
        /* Copy cached values */
        astro.ra[0] = astro.ra[1];
        astro.ra[1] = astro.ra[2];
        astro.dec[0] = astro.dec[1];
        astro.dec[1] = astro.dec[2];
        astro.sid[0] = astro.sid[1];
        astro.sid[1] = astro.sid[2];
        astro.dra[0] = astro.dra[1];
        astro.dra[1] = astro.dra[2];
        astro.rsum[0] = astro.rsum[1];
        astro.rsum[1] = astro.rsum[2];
        /* Compute next day values */
        computeAstroDay(julianDay + 1, ad);
        astro.ra[2] = ad.ra;
        astro.dec[2] = ad.dec;
        astro.sid[2] = ad.sidtime;
        astro.dra[2] = ad.dra;
        astro.rsum[2] = ad.rsum;
    } else if (astro.jd == julianDay + 1) {
        /* Copy cached values */
        astro.ra[2] = astro.ra[1];
        astro.ra[1] = astro.ra[0];
        astro.dec[2] = astro.dec[1];
        astro.dec[1] = astro.dec[0];
        astro.sid[2] = astro.sid[1];
        astro.sid[1] = astro.sid[0];
        astro.dra[2] = astro.dra[1];
        astro.dra[1] = astro.dra[0];
        astro.rsum[2] = astro.rsum[1];
        astro.rsum[1] = astro.rsum[0];
        /* Compute previous day values */
        computeAstroDay(julianDay - 1, ad);
        astro.ra[0] = ad.ra;
        astro.dec[0] = ad.dec;
        astro.sid[0] = ad.sidtime;
        astro.dra[0] = ad.dra;
        astro.rsum[0] = ad.rsum;


    } else if (astro.jd != julianDay) {
        /* Compute 3 day values */
        computeAstroDay(julianDay - 1, ad);
        astro.ra[0] = ad.ra;
        astro.dec[0] = ad.dec;
        astro.sid[0] = ad.sidtime;
        astro.dra[0] = ad.dra;
        astro.rsum[0] = ad.rsum;
        computeAstroDay(julianDay, ad);
        astro.ra[1] = ad.ra;
        astro.dec[1] = ad.dec;
        astro.sid[1] = ad.sidtime;
        astro.dra[1] = ad.dra;
        astro.rsum[1] = ad.rsum;
        computeAstroDay(julianDay + 1, ad);
        astro.ra[2] = ad.ra;
        astro.dec[2] = ad.dec;
        astro.sid[2] = ad.sidtime;
        astro.dra[2] = ad.dra;
        astro.rsum[2] = ad.rsum;

    }

    astro.jd = julianDay;
    computeTopAstro(loc, astro, topAstro);

} static double getJulianDay(SDate date, double gmt) {
    double jdB = 0, jdY, jdM, JD;

    jdY = date.year;
    jdM = date.month;

    if (date.month <= 2) {
        jdY--;
        jdM += 12;
    }

    if (date.year < 1)
        jdY++;

    if ((date.year > 1582) || ((date.year == 1582) &&
            ((date.month > 10) ||
                    ((date.month == 10) && (date.day >= 4)))))
        jdB = 2 - floor(jdY / 100.0) + floor((jdY / 100.0) / 4.0);

    JD = floor(365.25 * (jdY + 4716.0)) + floor(30.6001 * (jdM + 1))
            + (date.day + (-gmt) / 24.0) + jdB - 1524.5;

    JD = JD + (computeDeltaT(date.year) / 86400.0);
    return JD;

} static double getSunrise(Location loc, Astro tastro) {
    return getRiseSet(loc, tastro, Type.SUNRISE);
} static double getSunset(Location loc, Astro tastro) {
    return getRiseSet(loc, tastro, Type.SUNSET);
} static double getTransit(double lon, Astro tastro) {

    double M, sidG;
    double ra0 = tastro.ra[0], ra2 = tastro.ra[2];
    double A, H;

    M = ((tastro.ra[1] - lon - tastro.sid[1]) / 360.0);
    M = limitAngle1(M);

    /* Sidereal time at Greenwich (p. 103) */
    sidG = tastro.sid[1] + 360.985647 * M;

    if (tastro.ra[1] > 350 && tastro.ra[2] < 10)
        ra2 += 360;
    if (tastro.ra[0] > 350 && tastro.ra[1] < 10)
        ra0 = 0;

    /* Interpolation of 1-day intervals (pp. 24-25) */
    A = tastro.ra[1] +
            (M * ((tastro.ra[1] - ra0) + (ra2 - tastro.ra[1]) +
                    ((ra2 - tastro.ra[1]) - (tastro.ra[1] - ra0)) * M) / 2.0);

    H = limitAngle180between(sidG + lon - A);

    return 24.0 * (M - (H / 360.0));
}
import org.arabeyes.itl.prayertime.AstroModule.Astro;
import static java.lang.Math.abs;
import static java.lang.Math.acos;
import static java.lang.Math.atan;
import static java.lang.Math.atan2;
import static java.lang.Math.ceil;
import static java.lang.Math.cos;
import static java.lang.Math.floor;
import static java.lang.Math.sin;
import static java.lang.Math.tan;
import static org.arabeyes.itl.prayertime.AstroModule.DEG_TO_10_BASE;
import static org.arabeyes.itl.prayertime.AstroModule.DEG_TO_RAD;
import static org.arabeyes.itl.prayertime.AstroModule.INVALID_TRIGGER;
import static org.arabeyes.itl.prayertime.AstroModule.RAD_TO_DEG;
import static org.arabeyes.itl.prayertime.AstroModule.getAstroValuesByDay;
import static org.arabeyes.itl.prayertime.AstroModule.getJulianDay;
import static org.arabeyes.itl.prayertime.AstroModule.getSunrise;
import static org.arabeyes.itl.prayertime.AstroModule.getSunset;
import static org.arabeyes.itl.prayertime.AstroModule.getTransit;
/*  Copyright (c) 2003-2006, 2009, Arabeyes, Thamer Mahmoud
 *
 *  A full featured Muslim Prayer Times calculator
 *
 * (www.arabeyes.org - under LGPL license - see COPYING file)
 */
package org.arabeyes.itl.prayertime;



class PrayerModule {
    // Compatible with ITL 59bd87234aa87712a92b3fffb5497a43f121abf2

    /* This holds the current date info. */
    static class SDate {
        int day;
        int month;
        int year;

        SDate() {
        }

        SDate(SDate src) {
            this.day = src.day;
            this.month = src.month;
            this.year = src.year;
        }
    }

    /**
     * This holds the location info.
     */
    static class Location {
        double degreeLong;  /* Longitude in decimal degree. */
        double degreeLat;   /* Latitude in decimal degree. */
        double gmtDiff;     /* GMT difference at regular time. */
        int dst;            /* Daylight savings time switch (0 if not used).
                               Setting this to 1 should add 1 hour to all the
                               calculated prayer times */
        double seaLevel;    /* Height above Sea level in meters */
        double pressure;    /* Atmospheric pressure in millibars (the
                               astronomical standard value is 1010) */
        double temperature; /* Temperature in Celsius degree (the astronomical
                               standard value is 10) */

        Location() {
        }

        Location(Location src) {
            this.degreeLong = src.degreeLong;
            this.degreeLat = src.degreeLat;
            this.gmtDiff = src.gmtDiff;
            this.dst = src.dst;
            this.seaLevel = src.seaLevel;
            this.pressure = src.pressure;
            this.temperature = src.temperature;
        }
    }

    /* Defaults */
    private static final double KAABA_LAT = 21.423333;
    private static final double KAABA_LONG = 39.823333;
    private static final double DEF_NEAREST_LATITUDE = 48.5;
    private static final double DEF_EXTREME_LATITUDE = 55.0;
    private static final double DEF_IMSAAK_ANGLE = 1.5;
    private static final int DEF_IMSAAK_INTERVAL = 10;
    private static final int DEF_ROUND_SEC = 30;
    private static final int AGGRESSIVE_ROUND_SEC = 1;

    private PrayerModule() {
    }

    /* Astro astroCache;  This global variable is used for caching values between
     * multiple getPrayerTimesByDay() calls. You can disable this
     * caching feature by moving this line to the start of the
     * getPrayerTimesByDay() function. */

    /**
     * The "getPrayerTimes" function fills an array of six Prayer structures
     * "Prayer[6]". This list contains the prayer minutes and hours information
     * like this:
     * <p>
     * - Prayer[0].minute    is today's Fajr minutes
     * - Prayer[1].hour      is today's Shorooq hours
     * - ... and so on until...
     * - Prayer[5].minute    is today's Ishaa minutes
     */
    static PrayerTime[] getPrayerTimes(Location loc, Method conf, SDate date) {
        PrayerTime[] pt = new PrayerTime[6];
        for (int i = 0; i < pt.length; ++i)
            pt[i] = new PrayerTime();
        DayInfo di = getDayInfo(date, loc.gmtDiff);
        getPrayerTimesByDay(loc, conf, di.lastDay, di.dayOfYear, di.julianDay, pt, TimeType.FAJR);
        return pt;
    }

    private static void getPrayerTimesByDay(Location loc, Method conf,
                                            int lastDay, int dayOfYear, double julianDay,
                                            PrayerTime[] pt, TimeType type) {

        int i, invalid;
        double zu, sh, mg, fj, is, ar;
        double lat, lon, dec;
        double[] tempPrayer = new double[6];
        /* made as a local variable to avoid race condition between threads */
        Astro astroCache = new Astro();
        Astro tAstro = new Astro();

        lat = loc.degreeLat;
        lon = loc.degreeLong;
        invalid = 0;

        /* Start by filling the tAstro structure with the appropriate astronomical
         * values for this day. We also pass the cache structure to update and check
         * if the actual values are already available. */
        getAstroValuesByDay(julianDay, loc, astroCache, tAstro);
        dec = DEG_TO_RAD(tAstro.dec[1]);

        /* Get Prayer Times formulae results for this day of year and this
         * setLocation. The results are NOT the actual prayer times */
        fj = getFajIsh(lat, dec, conf.fajrAng);
        sh = getSunrise(loc, tAstro);