59d799dabc
* Moved the ExpressionParser class to shared. It's now built into its own static library. * Added hexadecimal number support to the expression parser as well as Evaluation*() methods to get a number instead of a string. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31298 a95241bf-73f2-0310-859d-f6bbb57e9c96
285 lines
5.4 KiB
C
285 lines
5.4 KiB
C
|
|
/*
|
|
* M_APM - mapm_gcd.c
|
|
*
|
|
* Copyright (C) 2001 - 2007 Michael C. Ring
|
|
*
|
|
* Permission to use, copy, and distribute this software and its
|
|
* documentation for any purpose with or without fee is hereby granted,
|
|
* provided that the above copyright notice appear in all copies and
|
|
* that both that copyright notice and this permission notice appear
|
|
* in supporting documentation.
|
|
*
|
|
* Permission to modify the software is granted. Permission to distribute
|
|
* the modified code is granted. Modifications are to be distributed by
|
|
* using the file 'license.txt' as a template to modify the file header.
|
|
* 'license.txt' is available in the official MAPM distribution.
|
|
*
|
|
* This software is provided "as is" without express or implied warranty.
|
|
*/
|
|
|
|
/*
|
|
* $Id: mapm_gcd.c,v 1.8 2007/12/03 01:41:05 mike Exp $
|
|
*
|
|
* This file contains the GCD and LCM functions
|
|
*
|
|
* $Log: mapm_gcd.c,v $
|
|
* Revision 1.8 2007/12/03 01:41:05 mike
|
|
* Update license
|
|
*
|
|
* Revision 1.7 2003/07/21 20:16:43 mike
|
|
* Modify error messages to be in a consistent format.
|
|
*
|
|
* Revision 1.6 2003/03/31 22:12:33 mike
|
|
* call generic error handling function
|
|
*
|
|
* Revision 1.5 2002/11/03 22:44:21 mike
|
|
* Updated function parameters to use the modern style
|
|
*
|
|
* Revision 1.4 2002/05/17 22:17:47 mike
|
|
* fix comment
|
|
*
|
|
* Revision 1.3 2002/05/17 22:16:36 mike
|
|
* move even/odd util functions to mapmutl2
|
|
*
|
|
* Revision 1.2 2001/07/15 20:55:20 mike
|
|
* add comments
|
|
*
|
|
* Revision 1.1 2001/07/15 20:48:27 mike
|
|
* Initial revision
|
|
*/
|
|
|
|
#include "m_apm_lc.h"
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
* From Knuth, The Art of Computer Programming:
|
|
*
|
|
* This is the binary GCD algorithm as described
|
|
* in the book (Algorithm B)
|
|
*/
|
|
void m_apm_gcd(M_APM r, M_APM u, M_APM v)
|
|
{
|
|
M_APM tmpM, tmpN, tmpT, tmpU, tmpV;
|
|
int kk, kr, mm;
|
|
long pow_2;
|
|
|
|
/* 'is_integer' will return 0 || 1 */
|
|
|
|
if ((m_apm_is_integer(u) + m_apm_is_integer(v)) != 2)
|
|
{
|
|
M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_gcd\', Non-integer input");
|
|
|
|
M_set_to_zero(r);
|
|
return;
|
|
}
|
|
|
|
if (u->m_apm_sign == 0)
|
|
{
|
|
m_apm_absolute_value(r, v);
|
|
return;
|
|
}
|
|
|
|
if (v->m_apm_sign == 0)
|
|
{
|
|
m_apm_absolute_value(r, u);
|
|
return;
|
|
}
|
|
|
|
tmpM = M_get_stack_var();
|
|
tmpN = M_get_stack_var();
|
|
tmpT = M_get_stack_var();
|
|
tmpU = M_get_stack_var();
|
|
tmpV = M_get_stack_var();
|
|
|
|
m_apm_absolute_value(tmpU, u);
|
|
m_apm_absolute_value(tmpV, v);
|
|
|
|
/* Step B1 */
|
|
|
|
kk = 0;
|
|
|
|
while (TRUE)
|
|
{
|
|
mm = 1;
|
|
if (m_apm_is_odd(tmpU))
|
|
break;
|
|
|
|
mm = 0;
|
|
if (m_apm_is_odd(tmpV))
|
|
break;
|
|
|
|
m_apm_multiply(tmpN, MM_0_5, tmpU);
|
|
m_apm_copy(tmpU, tmpN);
|
|
|
|
m_apm_multiply(tmpN, MM_0_5, tmpV);
|
|
m_apm_copy(tmpV, tmpN);
|
|
|
|
kk++;
|
|
}
|
|
|
|
/* Step B2 */
|
|
|
|
if (mm)
|
|
{
|
|
m_apm_negate(tmpT, tmpV);
|
|
goto B4;
|
|
}
|
|
|
|
m_apm_copy(tmpT, tmpU);
|
|
|
|
/* Step: */
|
|
|
|
B3:
|
|
|
|
m_apm_multiply(tmpN, MM_0_5, tmpT);
|
|
m_apm_copy(tmpT, tmpN);
|
|
|
|
/* Step: */
|
|
|
|
B4:
|
|
|
|
if (m_apm_is_even(tmpT))
|
|
goto B3;
|
|
|
|
/* Step B5 */
|
|
|
|
if (tmpT->m_apm_sign == 1)
|
|
m_apm_copy(tmpU, tmpT);
|
|
else
|
|
m_apm_negate(tmpV, tmpT);
|
|
|
|
/* Step B6 */
|
|
|
|
m_apm_subtract(tmpT, tmpU, tmpV);
|
|
|
|
if (tmpT->m_apm_sign != 0)
|
|
goto B3;
|
|
|
|
/*
|
|
* result = U * 2 ^ kk
|
|
*/
|
|
|
|
if (kk == 0)
|
|
m_apm_copy(r, tmpU);
|
|
else
|
|
{
|
|
if (kk == 1)
|
|
m_apm_multiply(r, tmpU, MM_Two);
|
|
|
|
if (kk == 2)
|
|
m_apm_multiply(r, tmpU, MM_Four);
|
|
|
|
if (kk >= 3)
|
|
{
|
|
mm = kk / 28;
|
|
kr = kk % 28;
|
|
pow_2 = 1L << kr;
|
|
|
|
if (mm == 0)
|
|
{
|
|
m_apm_set_long(tmpN, pow_2);
|
|
m_apm_multiply(r, tmpU, tmpN);
|
|
}
|
|
else
|
|
{
|
|
m_apm_copy(tmpN, MM_One);
|
|
m_apm_set_long(tmpM, 0x10000000L); /* 2 ^ 28 */
|
|
|
|
while (TRUE)
|
|
{
|
|
m_apm_multiply(tmpT, tmpN, tmpM);
|
|
m_apm_copy(tmpN, tmpT);
|
|
|
|
if (--mm == 0)
|
|
break;
|
|
}
|
|
|
|
if (kr == 0)
|
|
{
|
|
m_apm_multiply(r, tmpU, tmpN);
|
|
}
|
|
else
|
|
{
|
|
m_apm_set_long(tmpM, pow_2);
|
|
m_apm_multiply(tmpT, tmpN, tmpM);
|
|
m_apm_multiply(r, tmpU, tmpT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
M_restore_stack(5);
|
|
}
|
|
/****************************************************************************/
|
|
/*
|
|
* u * v
|
|
* LCM(u,v) = ------------
|
|
* GCD(u,v)
|
|
*/
|
|
|
|
void m_apm_lcm(M_APM r, M_APM u, M_APM v)
|
|
{
|
|
M_APM tmpN, tmpG;
|
|
|
|
tmpN = M_get_stack_var();
|
|
tmpG = M_get_stack_var();
|
|
|
|
m_apm_multiply(tmpN, u, v);
|
|
m_apm_gcd(tmpG, u, v);
|
|
m_apm_integer_divide(r, tmpN, tmpG);
|
|
|
|
M_restore_stack(2);
|
|
}
|
|
/****************************************************************************/
|
|
|
|
#ifdef BIG_COMMENT_BLOCK
|
|
|
|
/*
|
|
* traditional GCD included for reference
|
|
* (also useful for testing ...)
|
|
*/
|
|
|
|
/*
|
|
* From Knuth, The Art of Computer Programming:
|
|
*
|
|
* To compute GCD(u,v)
|
|
*
|
|
* A1:
|
|
* if (v == 0) return (u)
|
|
* A2:
|
|
* t = u mod v
|
|
* u = v
|
|
* v = t
|
|
* goto A1
|
|
*/
|
|
void m_apm_gcd_traditional(M_APM r, M_APM u, M_APM v)
|
|
{
|
|
M_APM tmpD, tmpN, tmpU, tmpV;
|
|
|
|
tmpD = M_get_stack_var();
|
|
tmpN = M_get_stack_var();
|
|
tmpU = M_get_stack_var();
|
|
tmpV = M_get_stack_var();
|
|
|
|
m_apm_absolute_value(tmpU, u);
|
|
m_apm_absolute_value(tmpV, v);
|
|
|
|
while (TRUE)
|
|
{
|
|
if (tmpV->m_apm_sign == 0)
|
|
break;
|
|
|
|
m_apm_integer_div_rem(tmpD, tmpN, tmpU, tmpV);
|
|
m_apm_copy(tmpU, tmpV);
|
|
m_apm_copy(tmpV, tmpN);
|
|
}
|
|
|
|
m_apm_copy(r, tmpU);
|
|
M_restore_stack(4);
|
|
}
|
|
/****************************************************************************/
|
|
|
|
#endif
|
|
|