#include <stdio.h>
#include <math.h>

#define INTEGR_FUNCTION(x) sin((x))
#define INTEGR_FUNCTION_STR "sin(x)"
#define LOWER_LIMIT 0.2
#define UPPER_LIMIT 1.0
#define INTERVALS 50

typedef 
struct integr_task {
	double from;
	double to;
	double (*what)(double); /* интегрируемая функция */
	int nint; /* число интервалов */
} INTEGR_TASK;

typedef 
enum integr_error {
	INTEGR_OK = 0,
	INTEGR_NO_TASK_OR_RES,
	INTEGR_NO_FUNC,
	INTEGR_BAD_LIMITS,
	INTEGR_BAD_NINT,
	INTEGR_LAST_ERROR
} INTEGR_ERROR;

char *integr_error_str[INTEGR_LAST_ERROR+1] = {
	"Все хорошо",
	"Указатель на задание или результат равен NULL",
	"Указатель на функцию равен NULL",
	"Верхний предел меньше нижнего",
	"Неправильное число интервалов",
	"__INTEGR_LAST_ERROR__"
};

INTEGR_ERROR integrate_rect(
			INTEGR_TASK *task,
			double *result
);

#define INTEGRATE integrate_rect

double function(double arg)
{ 
	return INTEGR_FUNCTION(arg);
}

int main(void)
{

	double integral_val; 
	INTEGR_ERROR error;

	INTEGR_TASK test_task = {
		LOWER_LIMIT, 
		UPPER_LIMIT, 
		function, 
		INTERVALS
	};

	error = INTEGRATE(&test_task, &integral_val);

	if (error) {
		printf(
			"Ошибка в данных (%s).\n",
			integr_error_str[error]
		);
		return 1;
	};

	printf(
		"\nЗначение определенного\\
		 интеграла от функции f(x)\\
		  = %s\nв пределах от %.8f до %.8f: %.8f\n", 
		INTEGR_FUNCTION_STR, 
		LOWER_LIMIT,
		UPPER_LIMIT, 
		integral_val
	);

	return 0;
}

INTEGR_ERROR integrate_rect(
		INTEGR_TASK *task,
		double *result
		)
{
	double x, s, step;
	int j;

	/* проверка на корректность данных */
	if ((!task) || (!result)) {
		return INTEGR_NO_TASK_OR_RES;
	};

	if (!task->what) {
		return INTEGR_NO_FUNC;
	};

	if (task->from > task->to) {
		return INTEGR_BAD_LIMITS;
	};

	if (task->nint < 1) {
		return INTEGR_BAD_NINT;
	};

	/* собственно вычисление */	
	step = (task->to - task->from)/task->nint;
	x = task->from+step/2.0;
	s = 0;

	for (
		j = 1; 
		j <= task->nint; 
		j++, s += task->what(x), x += step
	);

	s *= step;
	*result = s;

	return INTEGR_OK;
}