/*
   ###########################################################################
   This PHP function performs arbitrary-precision integer fraction multipli-
   cation with reduction option.

   (A/B) * (C/D) = (A*C) / (B*D) = (E/F)

   E = A*C
   F = B*D

   To return the result reduced to lowest terms, set
   the ReduceFlag to TRUE.  The default is FALSE and
   will return the raw, un-reduced fraction.

   Reduced = G/H
   G = E / GCD
   H = F / GCD

   GCD = Greatest Common Divisor of both E and F
         If GCD == 1, then E/F cannot be reduced
         and G/H = E/F.

   The fractions may be composed of any signed integers,
   such as '48/-130' or '165/55'.

   ARGUMENTS:
   A_B = Signed integer fraction = 'A / B'
   C_D = Signed integer fraction = 'C / D'

   ERRORS:
   FALSE is returned if any of the arguments are non-numeric.

   NO DEPENDENCIES
   ###########################################################################
*/

   function BC_Mul_Frac ($A_B, $C_D, $ReduceFlag=FALSE)
{
// Read integer fraction argument strings
// and strip out ALL spaces from strings.
   $A_B = Str_Replace(' ', '', trim($A_B));
   $C_D = Str_Replace(' ', '', trim($C_D));

// Account for integer arguments and convert to 'X/1' format.
   if (StrPos($A_B, '/') === FALSE) {$A_B .= '/1';}
   if (StrPos($C_D, '/') === FALSE) {$C_D .= '/1';}

// Parse fraction strings and extract the individual integer values.
   list($A,$B) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', trim($A_B)));
   list($C,$D) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', trim($C_D)));

// Remove any redundant white space from arguments.
   $A = trim($A);   $B = trim($B);   $C = trim($C);   $D = trim($D);

// Error if any of the (A, B, C, D) arguments are non-numeric.
   if (
      !Is_Numeric($A) or !Is_Numeric($B)
   or !Is_Numeric($C) or !Is_Numeric($D)
      )
      {return FALSE;}

// Compute numerator and denominator of the multiplication
// and return resulting signed integer fraction string.
   $E = bcMul($A,$C);
   $F = bcMul($B,$D);

// If ReduceFlag === TRUE,  then reduce to lowest
// terms.  Otherwise return raw, unreduced value.
   if ($ReduceFlag === TRUE)
{
   $A = Str_Replace('-', '', Str_Replace('+', '', $E));
   $B = Str_Replace('-', '', Str_Replace('+', '', $F));
   if (bcComp($B,$A) < 0) {$w=$B;  $B=$A;  $GCD=$w;} else {$GCD=$A;}
   while ($B <> 0) {$w=$B;   $B=bcMod($GCD,$B);   $GCD=$w;}

// Reduce E/F to lowest terms
   $E = bcDiv($E, $GCD);
   $F = bcDiv($F, $GCD);
}
   return "$E/$F";

} // End of  BC_Mul_Frac (...)