!     Last change:  X     3 Oct 2004    2:55 pm
!Alex Beck
PROGRAM Binary_ASM
!-----------------------------------------------



IMPLICIT NONE
INTEGER :: Input1, Input2, i, j, k, base10
LOGICAL :: temp1, temp2, temp3
LOGICAL, DIMENSION(1:32) :: BN1, BN2, BN3, BS1, BS2, BS3, BNM1, BNM2, BNM3, RNA, RNS, RNM, CO, TM  !Binary Numbers 1, 2, and 3, Add, Sub,Mul
                                                                               !BN3 and BNM3 are the sum and product respectivly
                            !TM is temp Multiply, and RN is realnumber representation of a given number, addition or multiplication.
OPEN(1, FILE = "ProjectAssignment2.txt",STATUS = "REPLACE")

!Get the Binary numbers
WRITE (*,*) "Enter the first number within integer range: "
READ (*,*) Input1
WRITE (*,*) "Enter the second number within integer range: "
READ (*,*) Input2

BN1 = convertTo32IntBitWord(Input1)
BN2 = convertTo32IntBitWord(Input2)

WRITE (*,*) "BinaryNumber1is:",BN1
WRITE (*,*) "BinaryNumber1is:",BN1
WRITE (1,*) "BinaryNumber1is:",BN2
WRITE (1,*) "BinaryNumber1is:",BN2

BNM1 = BN1 !Preserve valuse for multiplication
BNM2 = BN2

BS1 = BN1 !Preserve valuse for subtraction
BS2 = BN2

BN3 = add(BN1,BN2)

base10 = Base2ToBase10(BN3)

WRITE (*,*) "Sum is: ", BN3
WRITE (*,*) "Sum is: ", Base10
WRITE (1,*) "Sum is: ", BN3
WRITE (1,*) "Sum is: ", Base10

RNA = RNconversion(BN3)

WRITE (*,*) "Sum as a real: ", RNA
WRITE (1,*) "Sum as a real: ", RNA

BS2(1) = .NOT. BS2(1)
BS3 = add(BS1,BS2)

base10 = Base2ToBase10(BS3)

WRITE (*,*) "Input1-Input2: ", BS3
WRITE (*,*) "Input1-Input2: ", Base10
WRITE (1,*) "Input1-Input2: ", BS3
WRITE (1,*) "Input1-Input2: ", Base10

RNS = RNconversion(BS3)

WRITE (*,*) "In1-In2 as real:", RNS
WRITE (1,*) "In1-In2 as real:", RNS

IF (BNM1(1) .EQV. BNM2(1)) THEN                   !Multiplication, sign determination
      BNM3(1) = .FALSE.
   ELSE
      BNM3(1) = .TRUE.
END IF
DO i = 32, 2, -1
   BNM3(i) = .FALSE.
END DO

DO i = 32, 2, -1

   DO j = 32, 1, -1
      TM(j) = .FALSE.  !Refreshes temp adding array
   END DO
   IF (BNM2(i) .EQV. .TRUE.) THEN
         DO j = i, 1, -1
            TM(j) = BNM1(j+32-i) !sets Temp adding array to proper digets of BNM1
         END DO
   END IF

   DO j = 32, 1, -1
      CO(j) = .FALSE.  !Refreshes temp adding array
   END DO
   DO k = 32, 2, -1
      temp1 = TM(k) .AND. BNM3(k)
      temp2 = (TM(k) .OR. BNM3(k)) .AND. (.NOT. temp1)
      temp3 = CO(k) .AND. temp2
      BNM3(k) = (CO(k) .OR. temp2) .AND. (.NOT. temp3)
      CO(k-1) = temp1 .OR. temp3
   End DO

   IF(CO(1) .EQV. .TRUE.) THEN !does not guarntee that all products above integer limit will be obseved by this statment.
         WRITE (*,*) "Product excedes integer limit for 1 word representation of integer."
         WRITE (1,*) "Product excedes integer limit for 1 word representation of integer."            
   End IF
END DO

base10 = Base2ToBase10(BNM3)

WRITE (*,*) "Product is: ", BNM3
WRITE (*,*) "Product is: ", Base10
WRITE (1,*) "Product is: ", BNM3
WRITE (1,*) "Product is: ", Base10

RNM = RNconversion(BNM3)

WRITE (*,*) "Productasareal:", RNM
WRITE (1,*) "Productasareal:", RNM

CLOSE (1)
STOP
CONTAINS




FUNCTION convertTo32IntBitWord(x) RESULT (B)
INTEGER :: i, xx
INTEGER, INTENT(IN) :: x
LOGICAL, DIMENSION(1:32) :: B
xx = x !because cannot redefine input varible

IF (xx < 0) THEN                !Determines sign of binary represnation of int
      B(1) = .TRUE.
     ELSE
      B(1) = .FALSE.
END IF
xx = ABS(xx)
DO i = 30, 0, -1                !Determines value of binary representations
   IF (xx/(2**i) > 0) THEN
      B(32 - i) = .TRUE.
   ELSE
      B(32 - i) = .FALSE.
   END IF
xx = MOD(xx,(2**i))
END DO

RETURN
END FUNCTION convertTo32IntBitWord




FUNCTION RNconversion(B) RESULT (R)
INTEGER :: i, j, c
LOGICAL, DIMENSION(1:32), INTENT(IN) :: B
LOGICAL, DIMENSION(1:32) :: R
DO i = 1, 32
   R(i) = .FALSE. !sets all R to false
END DO

R(1) = B(1)
c = 0                       !Real number determination for sum
DO i = 2, 32
   IF (B(i) .EQV. .TRUE.) THEN
         c = 159 - i
         EXIT
         END IF
END DO
!WRITE (*,*) "C= ", C
DO j = 2, 9
  IF (c/2**(9-j) > 0) THEN
         R(j) = .TRUE.
      ELSE
         R(j) = .FALSE.
   END IF
   c = MOD(c,2**(9-j))
END DO
j = 10
DO
   !write (*,*) R, "j",j,"i",i
   IF (j+i-9 <= 32 .AND. j <= 32) THEN
      R(j) = B(j+i-9)
      j = j+1
   ELSE
      EXIT
   END IF
END DO



RETURN
END FUNCTION RNconversion



FUNCTION Base2ToBase10(Q) RESULT(b)
INTEGER:: i, a, b, s
LOGICAL, DIMENSION (1:32), INTENT(IN) :: Q


b = 0
a = 0

IF (Q(1) .EQV. .FALSE.) THEN
   s = 1
ELSE
   s = -1
END IF
DO i=2, 32
  IF (Q(i) .EQV. .TRUE.) THEN
     a = s * (2**(32-i))
  ELSE
     a = 0
  END IF
     b = b + a
END DO

RETURN
END FUNCTION Base2ToBase10




FUNCTION add(Binary1,Binary2) RESULT (B3) !ADDs two binary representations and accounts perfectly for sign
INTEGER :: i, m
LOGICAL :: temp1, temp2, temp3, zero
LOGICAL, DIMENSION(1:32), INTENT(IN) :: Binary1,Binary2
LOGICAL, DIMENSION(1:32) :: CO, B1, B2, B3

zero = .FALSE.

B1 = Binary1
B2 = Binary2

IF (B1(1) .EQV. B2(1)) THEN       !Adding algorthym
   B3(1) = B1(1) !assigns sign to answer

   DO i = 32, 1, -1
      CO(i) = .FALSE.
   END DO
   DO i = 32, 2, -1
      temp1 = B1(i) .AND. B2(i)
      temp2 = (B1(i) .OR. B2(i)) .AND. (.NOT. temp1)
      temp3 = CO(i) .AND. temp2
      B3(i) = (CO(i) .OR. temp2) .AND. (.NOT. temp3)
      CO(i-1) = temp1 .OR. temp3
   End DO
      
   IF (CO(1) .EQV. .TRUE.) THEN
      WRITE (*,*) "Sum excedes integer limit for 1 word representation of integer."
      WRITE (1,*) "Sum excedes integer limit for 1 word representation of integer."
   End IF
                      
ELSE                       !Subtracting algorthym

   m = 2
   DO
      IF (m > 32) THEN
         WRITE (*,*) "The two numbers cancel eachother out perfectly to account for a 0 resultant."
         zero = .TRUE.
         EXIT
      END IF
      IF (B1(m) .EQV. B2(m)) THEN
         m = m + 1
      ELSE
         IF (B1(m) .EQV. .TRUE.) THEN !Checks to see which integer is greater
            B3(1) = B1(1)
            EXIT
         ELSE
            B3(1) = B2(1)
            EXIT
         END IF
      END IF
   END DO
      
   IF (zero .EQV. .FALSE.) THEN
      IF(B1(1) .EQV. B3(1)) THEN !Redetermines which integer is greater based on above assignment
         DO i = 2, 32
            IF (B1(i) .EQV. .TRUE.) THEN
               DO j = i, 32
                  B2(j) = .NOT. B2(j)
               END DO
               EXIT
            END IF
         END DO
         m = 32
         DO !Inverses smaller number and adds 1 to it.
            IF( m < 2)THEN
               WRITE (*,*) "There is an error in the previous Do loop."
               EXIT
            END IF
                     
            IF(B2(m) .EQV. .FALSE.) THEN
               B2(m) = .TRUE.
               DO i = m+1, 32
                  B2(i) = .FALSE.
               END DO
               EXIT
            ELSE
               m = m - 1
            END IF
         END DO
      ELSE
         DO i = 2, 32
            IF (B2(i) .EQV. .TRUE.) THEN
               DO j = i, 32
                  B1(j) = .NOT. B1(j)
               END DO
               EXIT
            END IF
         END DO
         m = 32
         DO !Inverses smaller number and adds 1 to it.
            IF( m < 2)THEN
               WRITE (*,*) "There is an error in the previous Do loop."
               EXIT
            END IF
                     
            IF(B1(m) .EQV. .FALSE.) THEN
               B1(m) = .TRUE.
               DO i = m+1, 32
                  B1(i) = .FALSE.
               END DO
               EXIT
            ELSE
               m = m - 1
            END IF
         END DO
      END IF
      !WRITE (*,*) B1
      !WRITE (*,*) B2
      DO i = 32, 1, -1
         CO(i) = .FALSE.
      END DO
      DO i = 32, 2, -1
         temp1 = B1(i) .AND. B2(i)
         temp2 = (B1(i) .OR. B2(i)) .AND. (.NOT. temp1)
         temp3 = CO(i) .AND. temp2
         B3(i) = (CO(i) .OR. temp2) .AND. (.NOT. temp3)
         CO(i-1) = temp1 .OR. temp3
      End DO
      DO i = 2, 32
         IF (B3(i) .EQV. .TRUE.) THEN
            B3(i) = .FALSE.
            EXIT
         END IF
      END DO
   ELSE
      DO i = 1 , 32
         B3(i) = .FALSE.
      END DO
   END IF
END IF
RETURN
END FUNCTION add

END PROGRAM Binary_ASM