C++ code v1.0 added

Hamid [2011-03-14 07:34:43]
C++ code v1.0 added
Filename
v1/cpp/CMakeLists.txt
v1/cpp/prayertimes.cpp
v1/cpp/prayertimes.hpp
diff --git a/v1/cpp/CMakeLists.txt b/v1/cpp/CMakeLists.txt
new file mode 100644
index 0000000..cc166a5
--- /dev/null
+++ b/v1/cpp/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.6)
+
+project(prayertimes)
+
+add_executable(prayertimes prayertimes.cpp)
+
+add_definitions(-Wall)
diff --git a/v1/cpp/prayertimes.cpp b/v1/cpp/prayertimes.cpp
new file mode 100644
index 0000000..431dfe1
--- /dev/null
+++ b/v1/cpp/prayertimes.cpp
@@ -0,0 +1,298 @@
+/*-------------------- In the name of God ----------------------*\
+
+    PrayerTimes 0.3
+    Islamic prayer times calculator
+
+Developed by:
+  Mohammad Ebrahim Mohammadi Panah <ebrahim at mohammadi dot ir>
+
+------------------------------------------------------------------
+
+Copyright 2009, Mohammad Ebrahim Mohammadi Panah
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You can get a copy of the GNU General Public License from
+http://www.gnu.org/copyleft/gpl.html
+
+\*--------------------------------------------------------------*/
+
+#include <ctime>
+#include <cmath>
+#include <cstring>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "prayertimes.hpp"
+
+#define PROG_NAME "prayertimes"
+#define PROG_NAME_FRIENDLY "PrayerTimes"
+#define PROG_VERSION "0.3"
+
+static const char* TimeName[] =
+{
+	"Fajr",
+	"Sunrise",
+	"Dhuhr",
+	"Asr",
+	"Sunset",
+	"Maghrib",
+	"Isha",
+};
+
+void print_help(FILE* f)
+{
+	fputs(PROG_NAME_FRIENDLY " " PROG_VERSION "\n\n", stderr);
+	fputs("Usage: " PROG_NAME " options...\n"
+	      "\n"
+		  " Options\n"
+	      "    --help                      -h  you're reading it\n"
+	      "    --version                   -v  prints name and version, then exits\n"
+	      "    --date arg                  -d  get prayer times for arbitrary date\n"
+	      "    --timezone arg              -z  get prayer times for arbitrary timezone\n"
+	      "  * --latitude arg              -l  latitude of desired location\n"
+	      "  * --longitude arg             -n  longitude of desired location\n"
+	      "    --calc-method arg           -c  select prayer time calculation method\n"
+	      "    --asr-juristic-method arg   -a  select Juristic method for calculating Asr prayer time\n"
+	      "    --high-lats-method arg      -i  select adjusting method for higher latitude\n"
+	      "    --dhuhr-minutes arg             minutes after mid-way for calculating Dhuhr prayer time\n"
+	      " ** --maghrib-minutes arg           minutes after sunset for calculating Maghrib prayer time\n"
+	      " ** --isha-minutes arg              minutes after Maghrib for calculating Isha prayer time\n"
+	      " ** --fajr-angle arg                angle for calculating Fajr prayer time\n"
+	      " ** --maghrib-angle arg             angle for calculating Maghrib prayer time\n"
+	      " ** --isha-angle arg                angle for calculating Isha prayer time\n"
+		  "\n"
+		  "  * These options are required\n"
+		  " ** By providing any of these options the calculation method is set to custom\n"
+	      "\n"
+		  " Possible arguments for --calc-method\n"
+	      "    jafari        Ithna Ashari\n"
+	      "    karachi       University of Islamic Sciences, Karachi\n"
+	      "    isna          Islamic Society of North America (ISNA)\n"
+	      "    mwl           Muslim World League (MWL)\n"
+	      "    makkah        Umm al-Qura, Makkah\n"
+	      "    egypt         Egyptian General Authority of Survey\n"
+	      "    custom        Custom Setting\n"
+          "\n"
+		  " Possible arguments for --asr-juristic-method\n"
+	      "    shafii        Shafii (standard)\n"
+	      "    hanafi        Hanafi\n"
+          "\n"
+		  " Possible arguments for --high-lats-method\n"
+	      "    none          No adjustment\n"
+	      "    midnight      middle of night\n"
+	      "    oneseventh    1/7th of night\n"
+	      "    anglebased    angle/60th of night\n"
+		  , stderr);
+
+}
+
+int main(int argc, char* argv[])
+{
+	PrayerTimes prayer_times;
+	double latitude = NAN;		// 35.7061
+	double longitude = NAN;		// 51.4358
+	time_t date = time(NULL);
+	double timezone = NAN;
+
+	// Parse options
+	for (;;)
+	{
+		static option long_options[] =
+		{
+			{ "help",                no_argument,       NULL, 'h' },
+			{ "version",             no_argument,       NULL, 'v' },
+			{ "date",                required_argument, NULL, 'd' },
+			{ "timezone",            required_argument, NULL, 'z' },
+			{ "latitude",            required_argument, NULL, 'l' },
+			{ "longitude",           required_argument, NULL, 'n' },
+			{ "calc-method",         required_argument, NULL, 'c' },
+			{ "asr-juristic-method", required_argument, NULL, 'a' },
+			{ "high-lats-method",    required_argument, NULL, 'i' },
+			{ "dhuhr-minutes",       required_argument, NULL, 0   },
+			{ "maghrib-minutes",     required_argument, NULL, 0   },
+			{ "isha-minutes",        required_argument, NULL, 0   },
+			{ "fajr-angle",          required_argument, NULL, 0   },
+			{ "maghrib-angle",       required_argument, NULL, 0   },
+			{ "isha-angle",          required_argument, NULL, 0   },
+			{ 0, 0, 0, 0 }
+		};
+
+		enum	// long options missing a short form
+		{
+			DHUHR_MINUTES = 9,
+			MAGHRIB_MINUTES,
+			ISHA_MINUTES,
+			FAJR_ANGLE,
+			MAGHRIB_ANGLE,
+			ISHA_ANGLE,
+		};
+
+		int option_index = 0;
+		int c = getopt_long(argc, argv, "hvd:z:l:n:c:a:i:", long_options, &option_index);
+
+		if (c == -1)
+			break;		// Last option
+
+		if (!optarg && c != 'h' && c != 'v')
+		{
+			fprintf(stderr, "Error: %s option requires an argument\n", long_options[option_index].name);
+			return 2;
+		}
+
+		switch (c)
+		{
+			case 0:
+				double arg;
+				if (sscanf(optarg, "%lf", &arg) != 1)
+				{
+					fprintf(stderr, "Error: Invalid number '%s'\n", optarg);
+					return 2;
+				}
+				switch (option_index)
+				{
+					case DHUHR_MINUTES:
+						prayer_times.set_dhuhr_minutes(arg);
+						break;
+					case MAGHRIB_MINUTES:
+						prayer_times.set_maghrib_minutes(arg);
+						break;
+					case ISHA_MINUTES:
+						prayer_times.set_isha_minutes(arg);
+						break;
+					case FAJR_ANGLE:
+						prayer_times.set_fajr_angle(arg);
+						break;
+					case MAGHRIB_ANGLE:
+						prayer_times.set_maghrib_angle(arg);
+						break;
+					case ISHA_ANGLE:
+						prayer_times.set_isha_angle(arg);
+						break;
+					default:
+						fprintf(stderr, "Error: Invalid command line option\n");
+						return 2;
+				}
+				break;
+			case 'h':		// --help
+				print_help(stdout);
+				return 0;
+			case 'v':		// --version
+				puts(PROG_NAME_FRIENDLY " " PROG_VERSION);
+				return 0;
+			case 'd':		// --date
+			{
+				tm* new_date = getdate(optarg);
+				if (!new_date)
+				{
+					fprintf(stderr, "Error: Failed to parse '%s' as date (%m)\n", optarg);
+					return 2;
+				}
+				date = mktime(new_date);
+				break;
+			}
+			case 'z':		// --timezone
+				if (sscanf(optarg, "%lf", &timezone) != 1)
+				{
+					fprintf(stderr, "Error: Invalid timezone '%s'\n", optarg);
+					return 2;
+				}
+				break;
+			case 'l':		// --latitude
+				if (sscanf(optarg, "%lf", &latitude) != 1)
+				{
+					fprintf(stderr, "Error: Invalid latitude '%s'\n", optarg);
+					return 2;
+				}
+				break;
+			case 'n':		// --longitude
+				if (sscanf(optarg, "%lf", &longitude) != 1)
+				{
+					fprintf(stderr, "Error: Invalid longitude '%s'\n", optarg);
+					return 2;
+				}
+				break;
+			case 'c':		// --calc-method
+				if (strcmp(optarg, "jafari") == 0)
+					prayer_times.set_calc_method(PrayerTimes::Jafari);
+				else if (strcmp(optarg, "karachi") == 0)
+					prayer_times.set_calc_method(PrayerTimes::Karachi);
+				else if (strcmp(optarg, "isna") == 0)
+					prayer_times.set_calc_method(PrayerTimes::ISNA);
+				else if (strcmp(optarg, "mwl") == 0)
+					prayer_times.set_calc_method(PrayerTimes::MWL);
+				else if (strcmp(optarg, "makkah") == 0)
+					prayer_times.set_calc_method(PrayerTimes::Makkah);
+				else if (strcmp(optarg, "egypt") == 0)
+					prayer_times.set_calc_method(PrayerTimes::Egypt);
+				else if (strcmp(optarg, "custom") == 0)
+					prayer_times.set_calc_method(PrayerTimes::Custom);
+				else
+				{
+					fprintf(stderr, "Error: Unknown method '%s'\n", optarg);
+					return 2;
+				}
+				break;
+			case 'a':		// --asr-juristic-method
+				if (strcmp(optarg, "shafii") == 0)
+					prayer_times.set_asr_method(PrayerTimes::Shafii);
+				else if (strcmp(optarg, "hanafi") == 0)
+					prayer_times.set_asr_method(PrayerTimes::Hanafi);
+				else
+				{
+					fprintf(stderr, "Error: Unknown method '%s'\n", optarg);
+					return 2;
+				}
+				break;
+			case 'i':		// --high-lats-method
+				if (strcmp(optarg, "none") == 0)
+					prayer_times.set_high_lats_adjust_method(PrayerTimes::None);
+				else if (strcmp(optarg, "midnight") == 0)
+					prayer_times.set_high_lats_adjust_method(PrayerTimes::MidNight);
+				else if (strcmp(optarg, "oneseventh") == 0)
+					prayer_times.set_high_lats_adjust_method(PrayerTimes::OneSeventh);
+				else if (strcmp(optarg, "anglebased") == 0)
+					prayer_times.set_high_lats_adjust_method(PrayerTimes::AngleBased);
+				else
+				{
+					fprintf(stderr, "Error: Unknown method '%s'\n", optarg);
+					return 2;
+				}
+				break;
+			default:
+				fprintf(stderr, "Error: Unknown option '%c'\n", c);
+				print_help(stderr);
+				return 2;
+		}
+	}
+
+	if (isnan(latitude) || isnan(longitude))
+	{
+		fprintf(stderr, "Error: You must provide both latitude and longitude\n");
+		return 2;
+	}
+
+	fputs(PROG_NAME_FRIENDLY " " PROG_VERSION "\n\n", stderr);
+
+	if (isnan(timezone))
+		timezone = PrayerTimes::get_effective_timezone(date);
+
+	double times[PrayerTimes::TimesCount];
+	fprintf(stderr, "date          : %s", ctime(&date));
+	fprintf(stderr, "timezone      : %.1lf\n", timezone);
+	fprintf(stderr, "latitude      : %.5lf\n", latitude);
+	fprintf(stderr, "longitude     : %.5lf\n", longitude);
+	puts("");
+	prayer_times.get_prayer_times(date, latitude, longitude, timezone, times);
+	for (int i = 0; i < PrayerTimes::TimesCount; ++i)
+		printf("%8s : %s\n", TimeName[i], PrayerTimes::float_time_to_time24(times[i]).c_str());
+	return 0;
+}
diff --git a/v1/cpp/prayertimes.hpp b/v1/cpp/prayertimes.hpp
new file mode 100644
index 0000000..ac0fcdf
--- /dev/null
+++ b/v1/cpp/prayertimes.hpp
@@ -0,0 +1,631 @@
+/*-------------------------- In the name of God ----------------------------*\
+
+    libprayertimes 1.0
+    Islamic prayer times calculator library
+    Based on PrayTimes 1.1 JavaScript library
+
+----------------------------- Copyright Block --------------------------------
+
+Copyright (C) 2007-2010 PrayTimes.org
+
+Developed By: Mohammad Ebrahim Mohammadi Panah <ebrahim at mohammadi dot ir>
+Based on a JavaScript Code By: Hamid Zarrabi-Zadeh
+
+License: GNU General Public License, ver 3
+
+TERMS OF USE:
+    Permission is granted to use this code, with or
+    without modification, in any website or application
+    provided that credit is given to the original work
+    with a link back to PrayTimes.org.
+
+This program is distributed in the hope that it will
+be useful, but WITHOUT ANY WARRANTY.
+
+PLEASE DO NOT REMOVE THIS COPYRIGHT BLOCK.
+
+------------------------------------------------------------------------------
+
+User's Manual:
+http://praytimes.org/manual
+
+Calculating Formulas:
+http://praytimes.org/calculation
+
+Code Repository:
+http://code.ebrahim.ir/prayertimes/
+
+\*--------------------------------------------------------------------------*/
+
+#include <cstdio>
+#include <cmath>
+#include <string>
+
+/* -------------------- PrayerTimes Class --------------------- */
+
+class PrayerTimes
+{
+public:
+	enum
+	{
+		VERSION_MAJOR = 1,
+		VERSION_MINOR = 0,
+	};
+/* --------------------- User Interface ----------------------- */
+/*
+	PrayerTimes(CalculationMethod calc_method = Jafari,
+			JuristicMethod asr_juristic = Shafii,
+			AdjustingMethod adjust_high_lats = MidNight,
+			double dhuhr_minutes = 0)
+
+	get_prayer_times(date, latitude, longitude, timezone, &times)
+	get_prayer_times(year, month, day, latitude, longitude, timezone, &times)
+
+	set_calc_method(method_id)
+	set_asr_method(method_id)
+	set_high_lats_adjust_method(method_id)		// adjust method for higher latitudes
+
+	set_fajr_angle(angle)
+	set_maghrib_angle(angle)
+	set_isha_angle(angle)
+	set_dhuhr_minutes(minutes)		// minutes after mid-day
+	set_maghrib_minutes(minutes)		// minutes after sunset
+	set_isha_minutes(minutes)		// minutes after maghrib
+
+	get_float_time_parts(time, &hours, &minutes)
+	float_time_to_time24(time)
+	float_time_to_time12(time)
+	float_time_to_time12ns(time)
+*/
+
+	// Calculation Methods
+	enum CalculationMethod
+	{
+		Jafari, 	// Ithna Ashari
+		Karachi,	// University of Islamic Sciences, Karachi
+		ISNA,   	// Islamic Society of North America (ISNA)
+		MWL,    	// Muslim World League (MWL)
+		Makkah, 	// Umm al-Qura, Makkah
+		Egypt,  	// Egyptian General Authority of Survey
+		Custom, 	// Custom Setting
+
+		CalculationMethodsCount
+	};
+
+	// Juristic Methods
+	enum JuristicMethod
+	{
+		Shafii,    // Shafii (standard)
+		Hanafi,    // Hanafi
+	};
+
+	// Adjusting Methods for Higher Latitudes
+	enum AdjustingMethod
+	{
+		None,      	// No adjustment
+		MidNight,  	// middle of night
+		OneSeventh,	// 1/7th of night
+		AngleBased,	// angle/60th of night
+	};
+
+	// Time IDs
+	enum TimeID
+	{
+		Fajr,
+		Sunrise,
+		Dhuhr,
+		Asr,
+		Sunset,
+		Maghrib,
+		Isha,
+
+		TimesCount
+	};
+
+/* -------------------- Interface Functions -------------------- */
+
+	PrayerTimes(CalculationMethod calc_method = Jafari,
+			JuristicMethod asr_juristic = Shafii,
+			AdjustingMethod adjust_high_lats = MidNight,
+			double dhuhr_minutes = 0)
+	: calc_method(calc_method)
+	, asr_juristic(asr_juristic)
+	, adjust_high_lats(adjust_high_lats)
+	, dhuhr_minutes(dhuhr_minutes)
+	{
+		method_params[Jafari]  = MethodConfig(16.0, false, 4.0, false, 14.0);	// Jafari
+		method_params[Karachi] = MethodConfig(18.0, true,  0.0, false, 18.0);	// Karachi
+		method_params[ISNA]    = MethodConfig(15.0, true,  0.0, false, 15.0);	// ISNA
+		method_params[MWL]     = MethodConfig(18.0, true,  0.0, false, 17.0);	// MWL
+		method_params[Makkah]  = MethodConfig(19.0, true,  0.0, true,  90.0);	// Makkah
+		method_params[Egypt]   = MethodConfig(19.5, true,  0.0, false, 17.5);	// Egypt
+		method_params[Custom]  = MethodConfig(18.0, true,  0.0, false, 17.0);	// Custom
+	}
+
+	/* return prayer times for a given date */
+	void get_prayer_times(int year, int month, int day, double _latitude, double _longitude, double _timezone, double times[])
+	{
+		latitude = _latitude;
+		longitude = _longitude;
+		timezone = _timezone;
+		julian_date = get_julian_date(year, month, day) - longitude / (double) (15 * 24);
+		compute_day_times(times);
+	}
+
+	/* return prayer times for a given date */
+	void get_prayer_times(time_t date, double latitude, double longitude, double timezone, double times[])
+	{
+		tm* t = localtime(&date);
+		get_prayer_times(1900 + t->tm_year, t->tm_mon + 1, t->tm_mday, latitude, longitude, timezone, times);
+	}
+
+	/* set the calculation method  */
+	void set_calc_method(CalculationMethod method_id)
+	{
+		calc_method = method_id;
+	}
+
+	/* set the juristic method for Asr */
+	void set_asr_method(JuristicMethod method_id)
+	{
+		asr_juristic = method_id;
+	}
+
+	/* set adjusting method for higher latitudes */
+	void set_high_lats_adjust_method(AdjustingMethod method_id)
+	{
+		adjust_high_lats = method_id;
+	}
+
+	/* set the angle for calculating Fajr */
+	void set_fajr_angle(double angle)
+	{
+		method_params[Custom].fajr_angle = angle;
+		calc_method = Custom;
+	}
+
+	/* set the angle for calculating Maghrib */
+	void set_maghrib_angle(double angle)
+	{
+		method_params[Custom].maghrib_is_minutes = false;
+		method_params[Custom].maghrib_value = angle;
+		calc_method = Custom;
+	}
+
+	/* set the angle for calculating Isha */
+	void set_isha_angle(double angle)
+	{
+		method_params[Custom].isha_is_minutes = false;
+		method_params[Custom].isha_value = angle;
+		calc_method = Custom;
+	}
+
+	/* set the minutes after mid-day for calculating Dhuhr */
+	void set_dhuhr_minutes(double minutes)
+	{
+		dhuhr_minutes = minutes;
+	}
+
+	/* set the minutes after Sunset for calculating Maghrib */
+	void set_maghrib_minutes(double minutes)
+	{
+		method_params[Custom].maghrib_is_minutes = true;
+		method_params[Custom].maghrib_value = minutes;
+		calc_method = Custom;
+	}
+
+	/* set the minutes after Maghrib for calculating Isha */
+	void set_isha_minutes(double minutes)
+	{
+		method_params[Custom].isha_is_minutes = true;
+		method_params[Custom].isha_value = minutes;
+		calc_method = Custom;
+	}
+
+	/* get hours and minutes parts of a float time */
+	static void get_float_time_parts(double time, int& hours, int& minutes)
+	{
+		time = fix_hour(time + 0.5 / 60);		// add 0.5 minutes to round
+		hours = floor(time);
+		minutes = floor((time - hours) * 60);
+	}
+
+	/* convert float hours to 24h format */
+	static std::string float_time_to_time24(double time)
+	{
+		if (isnan(time))
+			return std::string();
+		int hours, minutes;
+		get_float_time_parts(time, hours, minutes);
+		return two_digits_format(hours) + ':' + two_digits_format(minutes);
+	}
+
+	/* convert float hours to 12h format */
+	static std::string float_time_to_time12(double time, bool no_suffix = false)
+	{
+		if (isnan(time))
+			return std::string();
+		int hours, minutes;
+		get_float_time_parts(time, hours, minutes);
+		const char* suffix = hours >= 12 ? " PM" : " AM";
+		hours = (hours + 12 - 1) % 12 + 1;
+		return int_to_string(hours) + ':' + two_digits_format(minutes) + (no_suffix ? "" : suffix);
+	}
+
+	/* convert float hours to 12h format with no suffix */
+	static std::string float_time_to_time12ns(double time)
+	{
+		return float_time_to_time12(time, true);
+	}
+
+/* ---------------------- Time-Zone Functions ----------------------- */
+
+	/* compute local time-zone for a specific date */
+	static double get_effective_timezone(time_t local_time)
+	{
+		tm* tmp = localtime(&local_time);
+		tmp->tm_isdst = 0;
+		time_t local = mktime(tmp);
+		tmp = gmtime(&local_time);
+		tmp->tm_isdst = 0;
+		time_t gmt = mktime(tmp);
+		return (local - gmt) / 3600.0;
+	}
+
+	/* compute local time-zone for a specific date */
+	static double get_effective_timezone(int year, int month, int day)
+	{
+		tm date = { 0 };
+		date.tm_year = year - 1900;
+		date.tm_mon = month - 1;
+		date.tm_mday = day;
+		date.tm_isdst = -1;		// determine it yourself from system
+		time_t local = mktime(&date);		// seconds since midnight Jan 1, 1970
+		return get_effective_timezone(local);
+	}
+
+private:
+/* ------------------- Calc Method Parameters -------------------- */
+
+	struct MethodConfig
+	{
+		MethodConfig()
+		{
+		}
+
+		MethodConfig(double fajr_angle,
+				bool maghrib_is_minutes,
+				double maghrib_value,
+				bool isha_is_minutes,
+				double isha_value)
+		: fajr_angle(fajr_angle)
+		, maghrib_is_minutes(maghrib_is_minutes)
+		, maghrib_value(maghrib_value)
+		, isha_is_minutes(isha_is_minutes)
+		, isha_value(isha_value)
+		{
+		}
+
+		double fajr_angle;
+		bool   maghrib_is_minutes;
+		double maghrib_value;		// angle or minutes
+		bool   isha_is_minutes;
+		double isha_value;		// angle or minutes
+	};
+
+/* ---------------------- Calculation Functions ----------------------- */
+
+	/* References: */
+	/* http://www.ummah.net/astronomy/saltime   */
+	/* http://aa.usno.navy.mil/faq/docs/SunApprox.html */
+
+	typedef std::pair<double, double> DoublePair;
+
+	/* compute declination angle of sun and equation of time */
+	DoublePair sun_position(double jd)
+	{
+		double d = jd - 2451545.0;
+		double g = fix_angle(357.529 + 0.98560028 * d);
+		double q = fix_angle(280.459 + 0.98564736 * d);
+		double l = fix_angle(q + 1.915 * dsin(g) + 0.020 * dsin(2 * g));
+
+		// double r = 1.00014 - 0.01671 * dcos(g) - 0.00014 * dcos(2 * g);
+		double e = 23.439 - 0.00000036 * d;
+
+		double dd = darcsin(dsin(e) * dsin(l));
+		double ra = darctan2(dcos(e) * dsin(l), dcos(l)) / 15.0;
+		ra = fix_hour(ra);
+		double eq_t = q / 15.0 - ra;
+
+		return DoublePair(dd, eq_t);
+	}
+
+	/* compute equation of time */
+	double equation_of_time(double jd)
+	{
+		return sun_position(jd).second;
+	}
+
+	/* compute declination angle of sun */
+	double sun_declination(double jd)
+	{
+		return sun_position(jd).first;
+	}
+
+	/* compute mid-day (Dhuhr, Zawal) time */
+	double compute_mid_day(double _t)
+	{
+		double t = equation_of_time(julian_date + _t);
+		double z = fix_hour(12 - t);
+		return z;
+	}
+
+	/* compute time for a given angle G */
+	double compute_time(double g, double t)
+	{
+		double d = sun_declination(julian_date + t);
+		double z = compute_mid_day(t);
+		double v = 1.0 / 15.0 * darccos((-dsin(g) - dsin(d) * dsin(latitude)) / (dcos(d) * dcos(latitude)));
+		return z + (g > 90.0 ? - v :  v);
+	}
+
+	/* compute the time of Asr */
+	double compute_asr(int step, double t)  // Shafii: step=1, Hanafi: step=2
+	{
+		double d = sun_declination(julian_date + t);
+		double g = -darccot(step + dtan(fabs(latitude - d)));
+		return compute_time(g, t);
+	}
+
+/* ---------------------- Compute Prayer Times ----------------------- */
+
+	// array parameters must be at least of size TimesCount
+
+	/* compute prayer times at given julian date */
+	void compute_times(double times[])
+	{
+		day_portion(times);
+
+		times[Fajr]    = compute_time(180.0 - method_params[calc_method].fajr_angle, times[Fajr]);
+		times[Sunrise] = compute_time(180.0 - 0.833, times[Sunrise]);
+		times[Dhuhr]   = compute_mid_day(times[Dhuhr]);
+		times[Asr]     = compute_asr(1 + asr_juristic, times[Asr]);
+		times[Sunset]  = compute_time(0.833, times[Sunset]);
+		times[Maghrib] = compute_time(method_params[calc_method].maghrib_value, times[Maghrib]);
+		times[Isha]    = compute_time(method_params[calc_method].isha_value, times[Isha]);
+	}
+
+
+	/* compute prayer times at given julian date */
+	void compute_day_times(double times[])
+	{
+		double default_times[] = { 5, 6, 12, 13, 18, 18, 18 };		// default times
+		for (int i = 0; i < TimesCount; ++i)
+			times[i] = default_times[i];
+
+		for (int i = 0; i < NUM_ITERATIONS; ++i)
+			compute_times(times);
+
+		adjust_times(times);
+	}
+
+
+	/* adjust times in a prayer time array */
+	void adjust_times(double times[])
+	{
+		for (int i = 0; i < TimesCount; ++i)
+			times[i] += timezone - longitude / 15.0;
+		times[Dhuhr] += dhuhr_minutes / 60.0;		// Dhuhr
+		if (method_params[calc_method].maghrib_is_minutes)		// Maghrib
+			times[Maghrib] = times[Sunset] + method_params[calc_method].maghrib_value / 60.0;
+		if (method_params[calc_method].isha_is_minutes)		// Isha
+			times[Isha] = times[Maghrib] + method_params[calc_method].isha_value / 60.0;
+
+		if (adjust_high_lats != None)
+			adjust_high_lat_times(times);
+	}
+
+	/* adjust Fajr, Isha and Maghrib for locations in higher latitudes */
+	void adjust_high_lat_times(double times[])
+	{
+		double night_time = time_diff(times[Sunset], times[Sunrise]);		// sunset to sunrise
+
+		// Adjust Fajr
+		double fajr_diff = night_portion(method_params[calc_method].fajr_angle) * night_time;
+		if (isnan(times[Fajr]) || time_diff(times[Fajr], times[Sunrise]) > fajr_diff)
+			times[Fajr] = times[Sunrise] - fajr_diff;
+
+		// Adjust Isha
+		double isha_angle = method_params[calc_method].isha_is_minutes ? 18.0 : method_params[calc_method].isha_value;
+		double isha_diff = night_portion(isha_angle) * night_time;
+		if (isnan(times[Isha]) || time_diff(times[Sunset], times[Isha]) > isha_diff)
+			times[Isha] = times[Sunset] + isha_diff;
+
+		// Adjust Maghrib
+		double maghrib_angle = method_params[calc_method].maghrib_is_minutes ? 4.0 : method_params[calc_method].maghrib_value;
+		double maghrib_diff = night_portion(maghrib_angle) * night_time;
+		if (isnan(times[Maghrib]) || time_diff(times[Sunset], times[Maghrib]) > maghrib_diff)
+			times[Maghrib] = times[Sunset] + maghrib_diff;
+	}
+
+
+	/* the night portion used for adjusting times in higher latitudes */
+	double night_portion(double angle)
+	{
+		switch (adjust_high_lats)
+		{
+			case AngleBased:
+				return angle / 60.0;
+			case MidNight:
+				return 1.0 / 2.0;
+			case OneSeventh:
+				return 1.0 / 7.0;
+			default:
+				// Just to return something!
+				// In original library nothing was returned
+				// Maybe I should throw an exception
+				// It must be impossible to reach here
+				return 0;
+		}
+	}
+
+	/* convert hours to day portions  */
+	void day_portion(double times[])
+	{
+		for (int i = 0; i < TimesCount; ++i)
+			times[i] /= 24.0;
+	}
+
+/* ---------------------- Misc Functions ----------------------- */
+
+	/* compute the difference between two times  */
+	static double time_diff(double time1, double time2)
+	{
+		return fix_hour(time2 - time1);
+	}
+
+	static std::string int_to_string(int num)
+	{
+		char tmp[16];
+		tmp[0] = '\0';
+		sprintf(tmp, "%d", num);
+		return std::string(tmp);
+	}
+
+	/* add a leading 0 if necessary */
+	static std::string two_digits_format(int num)
+	{
+		char tmp[16];
+		tmp[0] = '\0';
+		sprintf(tmp, "%2.2d", num);
+		return std::string(tmp);
+	}
+
+/* ---------------------- Julian Date Functions ----------------------- */
+
+	/* calculate julian date from a calendar date */
+	double get_julian_date(int year, int month, int day)
+	{
+		if (month <= 2)
+		{
+			year -= 1;
+			month += 12;
+		}
+
+		double a = floor(year / 100.0);
+		double b = 2 - a + floor(a / 4.0);
+
+		return floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + b - 1524.5;
+	}
+
+	/* convert a calendar date to julian date (second method) */
+	double calc_julian_date(int year, int month, int day)
+	{
+		double j1970 = 2440588.0;
+		tm date = { 0 };
+		date.tm_year = year - 1900;
+		date.tm_mon = month - 1;
+		date.tm_mday = day;
+		date.tm_isdst = -1;		// determine it yourself from system
+		time_t ms = mktime(&date);		// seconds since midnight Jan 1, 1970
+		double days = floor(ms / (double) (60 * 60 * 24));
+		return j1970 + days - 0.5;
+	}
+
+/* ---------------------- Trigonometric Functions ----------------------- */
+
+	/* degree sin */
+	static double dsin(double d)
+	{
+		return sin(deg2rad(d));
+	}
+
+	/* degree cos */
+	static double dcos(double d)
+	{
+		return cos(deg2rad(d));
+	}
+
+	/* degree tan */
+	static double dtan(double d)
+	{
+		return tan(deg2rad(d));
+	}
+
+	/* degree arcsin */
+	static double darcsin(double x)
+	{
+		return rad2deg(asin(x));
+	}
+
+	/* degree arccos */
+	static double darccos(double x)
+	{
+		return rad2deg(acos(x));
+	}
+
+	/* degree arctan */
+	static double darctan(double x)
+	{
+		return rad2deg(atan(x));
+	}
+
+	/* degree arctan2 */
+	static double darctan2(double y, double x)
+	{
+		return rad2deg(atan2(y, x));
+	}
+
+	/* degree arccot */
+	static double darccot(double x)
+	{
+		return rad2deg(atan(1.0 / x));
+	}
+
+	/* degree to radian */
+	static double deg2rad(double d)
+	{
+		return d * M_PI / 180.0;
+	}
+
+	/* radian to degree */
+	static double rad2deg(double r)
+	{
+		return r * 180.0 / M_PI;
+	}
+
+	/* range reduce angle in degrees. */
+	static double fix_angle(double a)
+	{
+		a = a - 360.0 * floor(a / 360.0);
+		a = a < 0.0 ? a + 360.0 : a;
+		return a;
+	}
+
+	/* range reduce hours to 0..23 */
+	static double fix_hour(double a)
+	{
+		a = a - 24.0 * floor(a / 24.0);
+		a = a < 0.0 ? a + 24.0 : a;
+		return a;
+	}
+
+private:
+/* ---------------------- Private Variables -------------------- */
+
+	MethodConfig method_params[CalculationMethodsCount];
+
+	CalculationMethod calc_method;		// caculation method
+	JuristicMethod asr_juristic;		// Juristic method for Asr
+	AdjustingMethod adjust_high_lats;	// adjusting method for higher latitudes
+	double dhuhr_minutes;		// minutes after mid-day for Dhuhr
+
+	double latitude;
+	double longitude;
+	double timezone;
+	double julian_date;
+
+/* --------------------- Technical Settings -------------------- */
+
+	static const int NUM_ITERATIONS = 1;		// number of iterations needed to compute times
+};
ViewGit