//
// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// rational -- Rational numbers are numbers written as a ratio, i.e., as a fraction, where the numerator (top number)
//     and the denominator (bottom number) are whole numbers. When creating and computing with rational numbers, results
//     are constantly reduced to keep the numerator and denominator as small as possible.
//
// Author           : Peter A. Buhr
// Created On       : Wed Apr  6 17:56:25 2016
// Last Modified By : Peter A. Buhr
// Last Modified On : Mon May 15 21:30:12 2017
// Update Count     : 90
//

#ifndef RATIONAL_H
#define RATIONAL_H

#include "iostream"

trait scalar( otype T ) {
};

trait arithmetic( otype T | scalar( T ) ) {
	int !?( T );
	int ?==?( T, T );
	int ?!=?( T, T );
	int ?<?( T, T );
	int ?<=?( T, T );
	int ?>?( T, T );
	int ?>=?( T, T );
	void ?{}( T *, zero_t );
	void ?{}( T *, one_t );
	T +?( T );
	T -?( T );
	T ?+?( T, T );
	T ?-?( T, T );
	T ?*?( T, T );
	T ?/?( T, T );
	T ?%?( T, T );
	T ?/=?( T *, T );
	T abs( T );
};

// implementation

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
struct Rational {
	RationalImpl numerator, denominator;				// invariant: denominator > 0
}; // Rational

// constructors

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
void ?{}( Rational(RationalImpl) * r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
void ?{}( Rational(RationalImpl) * r, RationalImpl n );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
void ?{}( Rational(RationalImpl) * r, RationalImpl n, RationalImpl d );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
void ?{}( Rational(RationalImpl) * r, zero_t );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
void ?{}( Rational(RationalImpl) * r, one_t );

// getter for numerator/denominator

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
RationalImpl numerator( Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
RationalImpl denominator( Rational(RationalImpl) r );
forall ( otype RationalImpl | arithmetic( RationalImpl ) )
[ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src );

// setter for numerator/denominator

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d );

// comparison

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r );

// arithmetic

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
Rational(RationalImpl) +?( Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
Rational(RationalImpl) -?( Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r );

// conversion
forall ( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
double widen( Rational(RationalImpl) r );
forall ( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl );  RationalImpl convert( double );} )
Rational(RationalImpl) narrow( double f, RationalImpl md );

// I/O
forall ( otype RationalImpl | arithmetic( RationalImpl ) )
forall( dtype istype | istream( istype ) | { istype * ?|?( istype *, RationalImpl * ); } )
istype * ?|?( istype *, Rational(RationalImpl) * );

forall ( otype RationalImpl | arithmetic( RationalImpl ) )
forall( dtype ostype | ostream( ostype ) | { ostype * ?|?( ostype *, RationalImpl ); } )
ostype * ?|?( ostype *, Rational(RationalImpl ) );

#endif // RATIONAL_H

// Local Variables: //
// mode: c //
// tab-width: 4 //
// End: //
