Show:
Fraction = (function() {
	var checkType = function(value, type) {
		if (typeof value !== type) {
			throw "It should be a " + type + ": " + value;
		}
		return value;
	};
	var checkIsNumber = function(value) {
		return checkType(value, 'number');
	};
	var checkIsInt = function(value) {
		checkIsNumber(value);
		if (value % 1 !== 0) {
			throw "It should be an int: " + value;
		}
		return value;
	};

	/**
	 * Initialize the Fraction, numerator and denominator
	 * @class Fraction
	 * @constructor
	 * @param {Integer} numerator of the fraction
	 * @param {Integer} denominator the fraction must not be equal to 0
	 */
	var Fraction = function(numerator, denominator, noCheck) {
		if (!noCheck) {
			checkIsInt(numerator);
			checkIsInt(denominator);
			if (denominator === 0) {
				throw "The denominator must not be zero";
			}
			if (denominator < 0) {
				numerator = -numerator;
				denominator = -denominator;
			}
		}
		this.numerator = numerator;
		this.denominator = denominator;
		this.normalize();
	};

	/**
	 *
	 * @method value
	 * @return {Number} the float number represented by the fraction
	 */
	Fraction.prototype.value = function() {
		return this.numerator / this.denominator;
	};

	/**
	 * clone the Fraction
	 *
	 * @method clone
	 * @return {Fraction} Returns a clone of the fraction
	 */
	Fraction.prototype.clone = function() {
		return new Fraction(this.numerator, this.denominator, true);
	};

	/**
	 * inverse the Fraction
	 *
	 * @method inverse
	 * @return {Fraction} Returns the inverse of the fraction
	 */
	Fraction.prototype.inverse = function() {
		return new Fraction(this.denominator, this.numerator);
	};
	/**
	 * pretty-printer, converts fractions into whole numbers and fractions
	 *
	 * @method toString
	 * @returns {String}
	 */
	Fraction.prototype.toString = function() {
		return this.numerator + "/" + this.denominator;

	};

	/**
	 * pretty-printer to support TeX notation (using with MathJax, KaTeX, etc)
	 *
	 * @method toTeX
	 * @returns {String}
	 */
	Fraction.prototype.toTeX = function(mixed) {
		var result = '';
		if ((this.numerator < 0) != (this.denominator < 0))
			result = '-';
		var numerator = Math.abs(this.numerator);
		var denominator = Math.abs(this.denominator);

		if (!mixed) {
			// We want a simple fraction, without wholepart extracted
			if (denominator === 1)
				return result + numerator;
			else
				return result + '\\frac{' + numerator + '}{' + denominator + '}';
		}
		var wholepart = Math.floor(numerator / denominator);
		numerator = numerator % denominator;
		if (wholepart !== 0)
			result += wholepart;
		if (numerator !== 0)
			result += '\\frac{' + numerator + '}{' + denominator + '}';
		return result.length > 0 ? result : '0';
	};

	/* destructively rescale the fraction by some integral factor */
	Fraction.prototype.rescale = function(factor) {
		this.numerator *= factor;
		this.denominator *= factor;
		return this;
	};

	/**
	 * Adds the value of this fraction to another, returning the result in reduced form.
	 *
	 * @method add
	 * @returns {Fraction}
	 */
	Fraction.prototype.add = function(b) {
		var a = this.clone();
		if (!(b instanceof Fraction)) {
			throw "must be a Fraction: " + b;
		}
		var td = a.denominator;
		a.rescale(b.denominator);
		a.numerator += b.numerator * td;
		return a.normalize();
	};

	/**
	 * Subtracts the value of another fraction from the value of this one, returning the result in reduced form
	 *
	 * @method subtract
	 * @returns {Fraction}
	 */
	Fraction.prototype.subtract = function(b) {
		var a = this.clone();
		if (!(b instanceof Fraction)) {
			throw "must be a Fraction: " + b;
		}
		var td = a.denominator;
		a.rescale(b.denominator);
		a.numerator -= b.numerator * td;

		return a.normalize();
	};

	Fraction.prototype.multiply = function(b) {
		var a = this.clone();
		a.numerator *= b.numerator;
		a.denominator *= b.denominator;
		return a.normalize();
	};

	Fraction.prototype.divide = function(b) {
		if (!(b instanceof Fraction)) {
			throw "must be a Fraction: " + b;
		}
		var a = this.clone();
		a.numerator *= b.denominator;
		a.denominator *= b.numerator;
		return a.normalize();
	};

	Fraction.prototype.mod = function(b) {
		checkIsInt(b);
		var a = this.clone();
		a.numerator %= b * a.denominator;
		return a.normalize();
	};

	Fraction.prototype.equals = function(b) {
		if (!(b instanceof Fraction)) {
			return false;
		}
		// fractions that are equal should have equal normalized forms
		return (this.numerator === b.numerator && this.denominator === b.denominator);
	};
	/**
	 * Compares this object to another based on size.
	 * @method compareTo
	 * @returns {Fraction}
	 */
	Fraction.prototype.compareTo = function(b) {
		if (!(b instanceof Fraction)) {
			throw "must be a Fraction: " + b;
		}
		if (this === b || this.equals(b)) {
			return 0;
		}
		var first = this.numerator * b.denominator;
		var second = b.numerator * this.denominator;
		if (first == second) {
			return 0;
		} else if (first < second) {
			return -1;
		} else {
			return 1;
		}
	};

	Fraction.prototype.normalize = function() {
		var gcf = Fraction.gcf(this.numerator, this.denominator);
		this.numerator /= gcf;
		this.denominator /= gcf;
		if (this.denominator < 0) {
			this.numerator *= -1;
			this.denominator *= -1;
		}
		return this;
	};
	/* . */
	// Adapted from Ratio.js
	/**
	 * Takes two numbers and returns their greatest common factor
	 *
	 * @static
	 * @method gcf
	 * @returns {Number}
	 */
	Fraction.gcf = function(a, b) {
		if (arguments.length < 2) {
			return a;
		}
		var c;
		a = Math.abs(a);
		b = Math.abs(b);
		while (b) {
			c = a % b;
			a = b;
			b = c;
		}
		return a;
	};
	/**
	 * parse a string of the format a/b to a Fraction
	 *
	 * @static
	 * @method parse
	 * @returns {Fraction}
	 */
	Fraction.parse = function(s) {
		var split = s.split('/');
		var n = parseInt(split[0].trim(), 10);
		if (isNaN(n)) {
			throw "can't parse: " + s;
		}
		if (split.length === 1) {
			return new Fraction(n, 1);
		} else {
			var d = parseInt(split[1].trim(), 10);
			if (isNaN(n)) {
				throw "can't parse: " + s;
			}
			return new Fraction(n, d);
		}
	};

	/**
	 *<code>Fraction</code> representation of 0.
	 * @property ZERO
	 * @type Fraction
	 * @static
	 * @final
	 */
	Fraction.ZERO = new Fraction(0, 1);
	/**
	 *<code>Fraction</code> representation of 1.
	 * @property ONE
	 * @type Fraction
	 * @static
	 * @final
	 */
	Fraction.ONE = new Fraction(1, 1);

	return Fraction;
})();