package body Dimensioned_Units is


   function "*" (Left, Right : Unit) return Unit is
   begin
      return Unit'(Left.M + Right.M,
                   Left.D + Right.D,
                   Left.T + Right.T,
                   Left.Magnitude * Right.Magnitude);
   end "*";


   function "*" (Left : Unit;  Right : Real) return Unit is
   begin
      return Unit'(Left.M, Left.D, Left.T, Left.Magnitude * Right);
   end "*";


   function "*" (Left : Real;  Right : Unit) return Unit is
   begin
      return Unit'(Right.M, Right.D, Right.T, Right.Magnitude * Left);
   end "*";


   function "+" (Left, Right : Unit) return Unit is
   begin
      if Left.D /= Right.D or Left.M /= Right.M or Left.T /= Right.T then
         raise Dimension_Error;
      end if;
      return Unit'(Left.M, Left.D, Left.T, Left.Magnitude + Right.Magnitude);
   end "+";


   function "-" (Left, Right : Unit) return Unit is
   begin
      if Left.D /= Right.D or Left.M /= Right.M or Left.T /= Right.T then
         raise Dimension_Error;
      end if;
      return Unit'(Left.M, Left.D, Left.T, Left.Magnitude - Right.Magnitude);
   end "-";


   function "-" (Left : Unit) return Unit is
   begin
      return Unit'(Left.M, Left.D, Left.T, -Left.Magnitude);
   end "-";


   function "/" (Left, Right : Unit) return Unit is
   begin
      return Unit'(Left.M - Right.M,
                   Left.D - Right.D,
                   Left.T - Right.T,
                   Left.Magnitude / Right.Magnitude);
   end "/";


   function "/" (Left : Unit;  Right : Real) return Unit is
   begin
      return Unit'(Left.M, Left.D, Left.T, Left.Magnitude / Right);
   end "/";


   function "/" (Left : Real;  Right : Unit) return Unit is
   begin
      return Unit'(-Right.M, -Right.D, -Right.T,  Left / Right.Magnitude);
   end "/";


   function "**" (Left : Unit;  Right : Integer) return Unit is
   begin
      return Unit'(Left.M * Right,
                   Left.D * Right,
                   Left.T * Right,
                   Left.Magnitude ** Right);
   end "**";


   function Value (This : Unit) return Real is
   begin
      return This.Magnitude;
   end Value;


   function Make (Value : Real;  M,D,T : Integer) return Unit is
   begin
      return Unit'(M, D, T, Magnitude => Value);
   end Make;


end Dimensioned_Units;

