[SUB] Fractions

Posted By: txesmi

[SUB] Fractions - 05/15/18 10:44

Hi!
I wrote a little module to work with fractions.

ifractions.h
Code:
#ifndef _IFRACTIONS_H_
#define _IFRACTIONS_H_

#define TEMPFRAC_COUNT   16

typedef struct IFRAC {
	int num;
	int den;
} IFRAC;

IFRAC *ifraction(int _num, int _den); // temporal ifrac

IFRAC *ifracSet(IFRAC *_ifracA, IFRAC *_ifracB);

IFRAC *ifracAdd(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracSub(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracDiff(IFRAC *_ifracR, IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracMul(IFRAC *_ifracA, IFRAC *_ifracB);
IFRAC *ifracDiv(IFRAC *_ifracA, IFRAC *_ifracB);

IFRAC *ifracSimplify(IFRAC *_ifrac);
IFRAC *ifracCommonDen(IFRAC *_ifracA, IFRAC *_ifracB);

var ifracToNum(IFRAC *_ifrac);
IFRAC *ifracForNum(IFRAC *_ifrac, var _n);

void ifracPrintf(IFRAC *_ifrac);

#include "ifractions.c"
#endif



ifractions.c
Code:
int _mathGCD(int _a, int _b) {
	for (;;) {
		if (_a == 0)
			return _b;
		_b %= _a;
		if (_b == 0)
			return _a;
		_a %= _b;
	}
}

int _mathLCM(int _a, int _b) {
	int _t = _mathGCD(_a, _b);
	if (!_t)
		return 0;
	return _a / _t * _b;
}

IFRAC _ifracTemp[TEMPFRAC_COUNT];
IFRAC *_ifracZero = {num = 0; den = 1;}


IFRAC *ifraction(int _num, int _den) {
	static int _i = 0;
	IFRAC *_ifrac = _ifracTemp + _i;
	_i = (_i + 1) % TEMPFRAC_COUNT;
	memcpy(_ifrac, &_num, sizeof(IFRAC));
	return ifracSimplify(_ifrac);
}

IFRAC *ifracSet(IFRAC *_ifracA, IFRAC *_ifracB) {
	memcpy(_ifracA, _ifracB, sizeof(IFRAC));
	return ifracSimplify(_ifracA);
}

IFRAC *ifracSimplify(IFRAC *_ifrac) {
	int _gcd = _mathGCD(abs(_ifrac->num), abs(_ifrac->den));
	if (_gcd) {
		_ifrac->num /= _gcd;
		_ifrac->den /= _gcd;
	}
	if ((_ifrac->num == 0) || (_ifrac->den == 0)) {
		memcpy(_ifrac, _ifracZero, sizeof(IFRAC));
	} else if (_ifrac->den < 0) {
		_ifrac->num *= -1;
		_ifrac->den *= -1;
	}
	return _ifrac;
}

IFRAC *ifracCommonDen(IFRAC *_ifracA, IFRAC *_ifracB) {
	int _lcm = _mathLCM(_ifracA->den, _ifracB->den);
	_ifracA->num *= _lcm / _ifracA->den;
	_ifracA->den = _lcm;
	_ifracB->num *= _lcm / _ifracB->den;
	_ifracB->den = _lcm;
	return _ifracA;
}

IFRAC *ifracAdd(IFRAC *_ifracA, IFRAC *_ifracB) {
	IFRAC *_ifracT = ifraction(_ifracB->num, _ifracB->den);
	ifracCommonDen(_ifracA, _ifracT);
	_ifracA->num += _ifracT->num;
	return ifracSimplify(_ifracA);
}

IFRAC *ifracSub(IFRAC *_ifracA, IFRAC *_ifracB) {
	IFRAC *_ifracT = ifraction(_ifracB->num, _ifracB->den);
	ifracCommonDen(_ifracA, _ifracT);
	_ifracA->num -= _ifracT->num;
	return ifracSimplify(_ifracA);
}

IFRAC *ifracDiff(IFRAC *_ifracR, IFRAC *_ifracA, IFRAC *_ifracB) {
	ifracSet(_ifracR, _ifracA);
	return ifracSub(_ifracR, _ifracB);
}

IFRAC *ifracMul(IFRAC *_ifracA, IFRAC *_ifracB) {
	_ifracA->num *= _ifracB->num;
	_ifracA->den *= _ifracB->den;
	return ifracSimplify(_ifracA);
}

IFRAC *ifracDiv(IFRAC *_ifracA, IFRAC *_ifracB) {
	_ifracA->num *= _ifracB->den;
	_ifracA->den *= _ifracB->num;
	return ifracSimplify(_ifracA);
}

var ifracToNum(IFRAC *_ifrac) {
	return (var)_ifrac->num / _ifrac->den;
}

IFRAC *ifracForNum(IFRAC *_ifrac, var _n) {
	_ifrac->num = _n << 10;
	_ifrac->den = 1024;
	return ifracSimplify(_ifrac);
}

void ifracPrintf(IFRAC *_ifrac) {
	printf("%d / %d", _ifrac->num, _ifrac->den);
}



Maybe a bit overheaded of simplification.

Enjoy!
Posted By: 3run

Re: [SUB] Fractions - 05/15/18 10:56

Thank you man! laugh
Posted By: txesmi

Re: [SUB] Fractions - 05/15/18 11:41

there was a bug...

You are welcome wink
© 2024 lite-C Forums