/*
    libparted - a library for manipulating disk partitions
    Copyright (C) 2000, 2007 Free Software Foundation, Inc.

    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 should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/

/**
 * \file natmath.c
 */

/**
 * \addtogroup PedAlignment
 *
 * \brief Alignment constraint model.
 *
 * This part of libparted models alignment constraints.
 *
 * @{
 */

#include <config.h>
#include <stdlib.h>
#include <parted/parted.h>
#include <parted/debug.h>
#include <parted/natmath.h>

/* Arrrghhh!  Why doesn't C have tuples? */
typedef struct {
	PedSector	gcd;		/* "converges" to the gcd */
	PedSector	x;
	PedSector	y;
} EuclidTriple;

static const PedAlignment _any = {
	offset:		0,
	grain_size:	1
};

const PedAlignment* ped_alignment_any = &_any;
const PedAlignment* ped_alignment_none = NULL;

/* This function returns "a mod b", the way C should have done it!
 * Mathematicians prefer -3 mod 4 to be 3.  Reason: division by N
 * is all about adding or subtracting N, and we like our remainders
 * to be between 0 and N - 1.
 */
PedSector
abs_mod (PedSector a, PedSector b)
{
	if (a < 0)
		return a % b + b;
	else
		return a % b;
}

/* Rounds a number down to the closest number that is a multiple of
 * grain_size.
 */
PedSector
ped_round_down_to (PedSector sector, PedSector grain_size)
{
	return sector - abs_mod (sector, grain_size);
}

inline PedSector
ped_div_round_up (PedSector numerator, PedSector divisor)
{
                return (numerator + divisor - 1) / divisor;
}

inline PedSector
ped_div_round_to_nearest (PedSector numerator, PedSector divisor)
{
                return (numerator + divisor/2) / divisor;
}

/* Rounds a number up to the closest number that is a multiple of
 * grain_size.
 */
PedSector
ped_round_up_to (PedSector sector, PedSector grain_size)
{
	if (sector % grain_size)
		return ped_round_down_to (sector, grain_size) + grain_size;
	else
		return sector;
}

/* Rounds a number to the closest number that is a multiple of grain_size. */
PedSector
ped_round_to_nearest (PedSector sector, PedSector grain_size)
{
	if (sector % grain_size > grain_size/2)
		return ped_round_up_to (sector, grain_size);
	else
		return ped_round_down_to (sector, grain_size);
}

/* This function returns the largest number that divides both a and b.
 * It uses the ancient Euclidean algorithm.
 */
PedSector
ped_greatest_common_divisor (PedSector a, PedSector b)
{
	PED_ASSERT (a >= 0, return 0);
	PED_ASSERT (b >= 0, return 0);

	/* Put the arguments in the "right" format.  (Recursive calls made by
	 * this function are always in the right format.)
	 */
	if (b > a)
		return ped_greatest_common_divisor (b, a);

	if (b)
		return ped_greatest_common_divisor (b, a % b);
	else
		return a;
}

/**
 * Initialize a preallocated piece of memory for an alignment object
 * (used by PedConstraint).
 *
 * The object will represent all sectors \e s for which the equation 
 * <tt>s = offset + X * grain_size</tt> holds.
 */
int
ped_alignment_init (PedAlignment* align, PedSector offset, PedSector grain_size)
{
	PED_ASSERT (align != NULL, return 0);

	if (grain_size < 0)
		return 0;

	if (grain_size)
		align->offset = abs_mod (offset, grain_size);
	else
		align->offset = offset;
	align->grain_size = grain_size;

	return 1;
}

/**
 * Return an alignment object (used by PedConstraint), representing all
 * PedSector's that are of the form <tt>offset + X * grain_size</tt>.
 */
PedAlignment*
ped_alignment_new (PedSector offset, PedSector grain_size)
{
	PedAlignment*	align;

	align = (PedAlignment*) ped_malloc (sizeof (PedAlignment));
	if (!align)
		goto error;

	if (!ped_alignment_init (align, offset, grain_size))
		goto error_free_align;

	return align;

error_free_align:
	ped_free (align);
error:
	return NULL;
}

/**
 * Free up memory associated with \p align.
 */
void
ped_alignment_destroy (PedAlignment* align)
{
	if (align)
		ped_free (align);
}

/**
 * Return a duplicate of \p align.
 */
PedAlignment*
ped_alignment_duplicate (const PedAlignment* align)
{
	if (!align)
		return NULL;
	return ped_alignment_new (align->offset, align->grain_size);
}

/* the extended Euclid algorithm.
 *
 * input:
 * 	a and b, a > b
 *
 * output:
 * 	gcd, x and y, such that:
 *
 * 	gcd = greatest common divisor of a and b
 * 	gcd = x*a + y*b
 */
EuclidTriple
extended_euclid (int a, int b)
{
	EuclidTriple	result;
	EuclidTriple	tmp;

	if (b == 0) {
		result.gcd = a;
		result.x = 1;
		result.y = 0;
		return result;
	}

	tmp = extended_euclid (b, a % b);
	result.gcd = tmp.gcd;
	result.x = tmp.y;
	result.y = tmp.x - (a/b) * tmp.y;
	return result;
}

/**
 * This function computes a PedAlignment object that describes the
 * intersection of two alignments.  That is, a sector satisfies the
 * new alignment object if and only if it satisfies both of the original
 * ones.  (See ped_alignment_is_aligned() for the meaning of "satisfies")
 * 
 * Apart from the trivial cases (where one or both of the alignment objects
 * constraints have no sectors that satisfy them), this is what we're trying to
 * do:
 *  - two input constraints: \p a and \p b.
 *  - the new grain_size is going to be the lowest common multiple of
 *  \p a->grain_size and \p b->grain_size
 *  - hard part - solve the simultaneous equations, for offset, where offset,
 *  X and Y are variables.  (Note: offset can be obtained from either X or Y,
 *  by substituing into either equation)
 * 
 * \code
 *  	offset = \p a->offset + X * \p a->grain_size		(1)
 *  	offset = \p b->offset + Y * \p b->grain_size		(2)
 * \endcode
 * 
 * or, abbreviated:
 *
 * \code
 *  	o = Ao + X*Ag		(1)
 *  	o = Bo + Y*Bg		(2)
 * 
 *  =>	Ao + X*Ag    = Bo + Y*Bg     (1) = (2)
 *  	X*Ag - Y*Bg  = Bo - Ao  (3)
 * \endcode
 *
 * As it turns out, there only exists a solution if (Bo - Ao) is a multiple
 * of the GCD of Ag and Bg.  Reason: all linear combinations of Ag and Bg are
 * multiples of the GCD.
 *
 * Proof:
 *
 * \code
 *	A * Ag + B * Bg
 *	= A * (\p a * gcd) + B * (\p b * gcd)
 *	= gcd * (A * \p a + B * \p b)
 * \endcode
 *
 * gcd is a factor of the linear combination.  QED
 * 
 * Anyway, \p a * Ag + \p b * Bg = gcd can be solved (for \p a, \p b and gcd) 
 * with Euclid's extended algorithm.  Then, we just multiply through by 
 * (Bo - Ao) / gcd to get (3).
 *
 * i.e.
 * \code
 * 	A * Ag + B * Bg				= gcd
 * 	A*(Bo-Ao)/gcd * Ag + B(Bo-Ao)/gcd * Bg	= gcd * (Bo-Ao)/gcd
 * 	X*Ag - Y*Bg				= Bo - Ao		(3)
 *
 * 	X = A*(Bo-Ao)/gcd
 * 	Y = - B*(Bo-Ao)/gcd
 * \endcode
 * 
 * then:
 * \code
 *  	o = Ao + X*Ag			(1)
 *	  = Ao + A*(Bo-Ao)/gcd*Ag
 *  	o = Bo + Y*Bg			(2)
 *	  = Bo - B*(Bo-Ao)/gcd*Ag
 * \endcode
 *
 * Thanks go to Nathan Hurst (njh@hawthorn.csse.monash.edu.au) for figuring
 * this algorithm out :-)
 *
 * \note Returned \c NULL is a valid PedAlignment object, and can be used
	for ped_alignment_*() function.
 *
 * \return a PedAlignment on success, \c NULL on failure
 */
PedAlignment*
ped_alignment_intersect (const PedAlignment* a, const PedAlignment* b)
{
	PedSector	new_grain_size;
	PedSector	new_offset;
	PedSector	delta_on_gcd;
	EuclidTriple	gcd_factors;

        
	if (!a || !b)
		return NULL;

        /*PED_DEBUG (0x10, "intersecting alignments (%d,%d) and (%d,%d)",
                        a->offset, a->grain_size, b->offset, b->grain_size);
        */
        
	if (a->grain_size < b->grain_size) {
		const PedAlignment*	tmp;
	        tmp = a; a = b; b = tmp;
	}

	/* weird/trivial case: where the solution space for "a" or "b" is
	 * either empty or contains exactly one solution
	 */
	if (a->grain_size == 0 && b->grain_size == 0) {
		if (a->offset == b->offset)
			return ped_alignment_duplicate (a);
		else
			return NULL;
	}

	/* general case */
	gcd_factors = extended_euclid (a->grain_size, b->grain_size);

	delta_on_gcd = (b->offset - a->offset) / gcd_factors.gcd;
	new_offset = a->offset + gcd_factors.x * delta_on_gcd * a->grain_size;
	new_grain_size = a->grain_size * b->grain_size / gcd_factors.gcd;

	/* inconsistency => no solution */
	if (new_offset
	    != b->offset - gcd_factors.y * delta_on_gcd * b->grain_size)
		return NULL;

	return ped_alignment_new (new_offset, new_grain_size);
}

/* This function returns the sector closest to "sector" that lies inside
 * geom and satisfies the alignment constraint.
 */
static PedSector
_closest_inside_geometry (const PedAlignment* align, const PedGeometry* geom,
			  PedSector sector)
{
	PED_ASSERT (align != NULL, return -1);

	if (!align->grain_size) {
		if (ped_alignment_is_aligned (align, geom, sector)
		    && (!geom || ped_geometry_test_sector_inside (geom,
				    				  sector)))
			return sector;
		else
			return -1;
	}

	if (sector < geom->start)
		sector += ped_round_up_to (geom->start - sector,
					   align->grain_size);
	if (sector > geom->end)
		sector -= ped_round_up_to (sector - geom->end,
					   align->grain_size);

	if (!ped_geometry_test_sector_inside (geom, sector))
		return -1;
	return sector;
}

/**
 * This function returns the closest sector to \p sector that lies inside
 * \p geom that satisfies the given alignment constraint \p align.  It prefers
 * sectors that are beyond \p sector (are not smaller than \p sector), 
 * but does not guarantee that this.
 *
 * \return a PedSector on success, \c -1 on failure
 */
PedSector
ped_alignment_align_up (const PedAlignment* align, const PedGeometry* geom,
			PedSector sector)
{
	PedSector	result;

	PED_ASSERT (align != NULL, return -1);

	if (!align->grain_size)
		result = align->offset;
	else
		result = ped_round_up_to (sector - align->offset,
			       		  align->grain_size)
			 + align->offset;

	if (geom)
		result = _closest_inside_geometry (align, geom, result);
	return result;
}

/**
 * This function returns the closest sector to \p sector that lies inside
 * \p geom that satisfies the given alignment constraint \p align.  It prefers
 * sectors that are before \p sector (are not larger than \p sector),
 * but does not guarantee that this.
 *
 * \return a PedSector on success, \c -1 on failure
 */
PedSector
ped_alignment_align_down (const PedAlignment* align, const PedGeometry* geom,
			  PedSector sector)
{
	PedSector	result;

	PED_ASSERT (align != NULL, return -1);

	if (!align->grain_size)
		result = align->offset;
	else
		result = ped_round_down_to (sector - align->offset,
			      		    align->grain_size)
			 + align->offset;

	if (geom)
		result = _closest_inside_geometry (align, geom, result);
	return result;
}

/* Returns either a or b, depending on which is closest to "sector". */
static PedSector
closest (PedSector sector, PedSector a, PedSector b)
{
	if (a == -1)
		return b;
	if (b == -1)
		return a;

	if (abs (sector - a) < abs (sector - b))
		return a;
	else
		return b;
}

/**
 * This function returns the sector that is closest to \p sector, 
 * satisfies the \p align constraint and lies inside \p geom.
 *
 * \return a PedSector on success, \c -1 on failure
 */
PedSector
ped_alignment_align_nearest (const PedAlignment* align, const PedGeometry* geom,
			     PedSector sector)
{
	PED_ASSERT (align != NULL, return -1);

	return closest (sector, ped_alignment_align_up (align, geom, sector),
			ped_alignment_align_down (align, geom, sector));
}

/**
 * This function returns 1 if \p sector satisfies the alignment 
 * constraint \p align and lies inside \p geom.
 *
 * \return \c 1 on success, \c 0 on failure
 */
int
ped_alignment_is_aligned (const PedAlignment* align, const PedGeometry* geom,
			  PedSector sector)
{
	if (!align)
		return 0;

	if (geom && !ped_geometry_test_sector_inside (geom, sector))
		return 0;

	if (align->grain_size)
		return (sector - align->offset) % align->grain_size == 0;
	else
		return sector == align->offset;
}

/**
 * @}
 */

