module rational_object
implicit none

  private
  public :: rational, &
            operator(+), operator(-), operator(*),&
            operator(/), assignment(=),&
            output, input

  type :: rational
    integer :: num    ! ¤À¤l
        integer :: denom  ! ¤À¥À
  end type rational
  ! ¥[ªk
  interface operator(+)
    module procedure  rat__rat_plus_rat
  end interface
  ! ´îªk
  interface operator(-)
    module procedure rat__rat_minus_rat
  end interface
  ! ­¼ªk
  interface operator(*)
    module procedure rat__rat_times_rat
  end interface
  ! °£ªk
  interface operator(/)
    module procedure rat__rat_div_rat
  end interface
  ! µ¥¸¹
  interface assignment(=)
    module procedure rat_eq_rat
    module procedure int_eq_rat
    module procedure real_eq_rat
  end interface

contains
  ! ¤À¼Æ=¤À¼Æ
  subroutine rat_eq_rat( rat1, rat2 )
    implicit none
    type(rational), intent(out):: rat1
    type(rational), intent(in) :: rat2
    ! ª½±µ§â¤À¤l,¤À¥À¬Ûµ¥´N¦n¤F
    rat1%num   = rat2%num
    rat1%denom = rat2%denom

    return
  end subroutine rat_eq_rat
  ! ¾ã¼Æ=¤À¼Æ
  subroutine int_eq_rat( int, rat )
    implicit none
    integer, intent(out):: int
    type(rational), intent(in) :: rat
    ! ¤À¤l°£¥H¤À¥À¨ÓÂà´«¦¨¾ã¼Æ
    int = rat%num / rat%denom

    return
  end subroutine int_eq_rat
  ! ¯BÂI¼Æ=¤À¼Æ
  subroutine real_eq_rat( float, rat )
    implicit none
    real, intent(out) :: float
    type(rational), intent(in) :: rat
    ! ¤À¤l°£¥H¤À¥À
    float = real(rat%num) / real(rat%denom)

    return
  end subroutine real_eq_rat
  ! ¤Æ²¤À¼Æ
  function reduse( a )
    implicit none
    type(rational), intent(in) :: a
        type(rational) :: temp
    integer :: b
        integer :: sign
    type(rational) :: reduse

        if ( a%num*a%denom > 0 ) then
          sign=1
        else
          sign=-1
        end if
        temp%num=abs(a%num)
        temp%denom=abs(a%denom)
    b=gcv(temp%num,temp%denom)  ! §ä¤À¤l»P¤À¥Àªº³Ì¤j¤½¦]¼Æ
        ! §â¤À¤l,¤À¥À¦P°£¥H³Ì¤j¤½¦]¼Æ
    reduse%num = temp%num/b*sign
    reduse%denom = temp%denom/b

    return
  end function reduse
  ! ¥ÎÁÓÂà¬Û°£ªk§ä³Ì¤j¤½¦]¼Æ
  function gcv(a,b)
    implicit none
    integer, intent(in) :: a,b
        integer :: big,small
        integer :: temp
    integer :: gcv

        big=max(a,b)
        small=min(a,b)

        do while( small>1 )
          temp=mod(big,small)
          if ( temp == 0 ) exit
          big=small
          small=temp
    end do

    gcv=small
    return
  end function gcv
  ! ¤À¼Æ¬Û¥[
  function rat__rat_plus_rat( rat1, rat2 )
    implicit none
    type(rational) :: rat__rat_plus_rat
    type(rational), intent(in) :: rat1,rat2
    type(rational) :: act
    ! b/a+d/c = ( b*c+d*a )/(a*c)
    act%denom= rat1%denom * rat2%denom  ! a*c
    act%num  = rat1%num*rat2%denom + rat2%num*rat1%denom ! (b*c+d*a)
    rat__rat_plus_rat = reduse(act) ! ¬ù¤À

    return
  end function rat__rat_plus_rat
  ! ¤À¼Æ¬Û´î
  function rat__rat_minus_rat( rat1, rat2 )
    implicit none
    type(rational) :: rat__rat_minus_rat
    type(rational), intent(in) :: rat1, rat2
    type(rational) :: temp
    ! b/a-d/c=(b*c-d*a)/(a*c)
    temp%denom = rat1%denom*rat2%denom ! a*c
    temp%num   = rat1%num*rat2%denom - rat2%num*rat1%denom ! (b*c-d*a)
    rat__rat_minus_rat = reduse( temp ) ! ¬ù¤À
  return
  end function rat__rat_minus_rat
  ! ¤À¼Æ¬Û­¼
  function rat__rat_times_rat( rat1, rat2 )
    implicit none
    type(rational) :: rat__rat_times_rat
    type(rational), intent(in) :: rat1, rat2
    type(rational) :: temp
    ! (b/a)*(d/c)=(b*d)/(a*c)
    temp%denom = rat1%denom* rat2%denom ! (a*c)
    temp%num   = rat1%num  * rat2%num   ! (b*d)
    rat__rat_times_rat = reduse(temp)   ! ¬ù¤À

    return
  end function rat__rat_times_rat
  ! ¤À¼Æ¬Û°£
  function rat__rat_div_rat( rat1, rat2 )
    implicit none
    type(rational) :: rat__rat_div_rat
    type(rational), intent(in) :: rat1, rat2
    type(rational) :: temp
    ! (b/a)/(d/c)=(b*c)/(a*d)
    temp%denom = rat1%denom* rat2%num   ! (a*d)
    temp%num   = rat1%num  * rat2%denom ! (b*c)
    rat__rat_div_rat = reduse(temp)     ! ¬ù¤À

    return
  end function rat__rat_div_rat
  ! ¿é¤J
  subroutine input(a)
    implicit none
    type(rational), intent(out) :: a

    write(*,*) "Input num of rational:"
    read(*,*)  a%num
    write(*,*) "Input denomination of rational:"
    read(*,*)  a%denom

    return
  end subroutine input
  ! ¿é¥X
  subroutine output(a)
    implicit none
    type(rational), intent(in) :: a

    if ( a%denom/=1 ) then
      write(*, "(1x,' (',I3,'/',I3,')' )") a%num,a%denom
    else
      write(*, "(1x,I3)" ) a%num
    end if

    return
  end subroutine output

end module rational_object
! ¥Dµ{¦¡
program ex1104
  use rational_object
  implicit none
  type(rational) :: a,b,c
  integer :: d
  real :: f

  call input(a)
  call input(b)
  c=a+b
  write(*,"(1x,A4)",advance="no") "a+b="
  call output(c)
  c=a-b
  write(*,"(1x,A4)",advance="no") "a-b="
  call output(c)
  c=a*b
  write(*,"(1x,A4)",advance="no") "a*b="
  call output(c)
  c=a/b
  write(*,"(1x,A4)",advance="no") "a/b="
  call output(c)
  d=c
  f=c
  write(*, "(i3,f6.2)" ) d,f
  stop
end program ex1104