module big_integers_module public :: print_big public :: print_factors public :: prime public :: assignment (=) public :: operator (+) public :: operator (-) public :: operator (*) public :: operator (/) public :: operator (**) public :: modulo public :: huge public :: sqrt public :: operator (==) public :: operator (/=) public :: operator (<=) public :: operator (<) public :: operator (>=) public :: operator (>) private :: big_gets_int, & big_gets_char, & big_plus_int, & big_plus_big, & big_minus_int, & big_minus_big, & big_times_int, & big_times_big, & big_div_int, & big_div_big, & big_power_int, & modulo_big_int, & modulo_big_big, & big_eq_int, & int_eq_big, & big_eq_big, & big_ne_int, & int_ne_big, & big_ne_big, & big_le_int, & int_le_big, & big_le_big, & big_ge_int, & int_ge_big, & big_ge_big, & big_lt_int, & int_lt_big, & big_lt_big, & big_gt_int, & int_gt_big, & big_gt_big, & huge_big, & big_base_to_power, & print_big_base, & sqrt_big intrinsic modulo intrinsic huge intrinsic sqrt ! This indicates the maximum number of decimal digits ! that a big integer may contain. integer, parameter, private :: nr_of_decimal_digits = 50 ! If the radix (returned by "radix(0)" of the integers on ! your system is not 2 change the following constant to ! the logarithm in the base 10 of the radix: log10(radix) real, parameter, private :: log_base_10_of_radix = 0.30103 integer, parameter, private :: & d = digits (0) / 2, & r = radix (0), & base = r ** d, & nr_of_digits = nr_of_decimal_digits / (log_base_10_of_radix * d) + 1 ! The base of the number system is r ** d, ! so that each "digit" is 0 to r**d - 1 type, public :: big_integer private integer, dimension (0 : nr_of_digits) & :: digit end type big_integer integer, parameter, private :: f_nr_of_digits = 3 * nr_of_digits interface assignment (=) module procedure big_gets_int, & big_gets_char end interface interface operator (+) module procedure big_plus_int, & big_plus_big end interface interface operator (-) module procedure big_minus_int, & big_minus_big end interface interface operator (*) module procedure big_times_int, & big_times_big end interface interface operator (/) module procedure big_div_int, & big_div_big end interface interface operator (**) module procedure big_power_int end interface interface modulo module procedure modulo_big_int, & modulo_big_big end interface interface operator (==) module procedure big_eq_int, & int_eq_big, & big_eq_big end interface interface operator (/=) module procedure big_ne_int, & int_ne_big, & big_ne_big end interface interface operator (<=) module procedure big_le_int, & int_le_big, & big_le_big end interface interface operator (>=) module procedure big_ge_int, & int_ge_big, & big_ge_big end interface interface operator (<) module procedure big_lt_int, & int_lt_big, & big_lt_big end interface interface operator (>) module procedure big_gt_int, & int_gt_big, & big_gt_big end interface interface huge module procedure huge_big end interface interface sqrt module procedure sqrt_big end interface contains subroutine big_gets_int (b, i) type (big_integer), intent (out) :: b integer, intent (in) :: i if (i < 0) then print *, "attempt to assign negative number" stop end if b % digit (0) = modulo (i, base) b % digit (1) = i / base b % digit (2:) = 0 end subroutine big_gets_int subroutine big_gets_char (b, c) type (big_integer), intent (out) :: b character (len=*), intent (in) :: c integer :: temp_digit, n if (len (c) > nr_of_decimal_digits) then b = huge (b) return end if b % digit = 0 do n = 1, len (c) temp_digit = index ("0123456789", c (n:n)) - 1 if (temp_digit < 0) then print *, "attempt to assign nonnumeric string" stop end if b = b * 10 + temp_digit end do end subroutine big_gets_char function big_base_to_power (n) result (b) integer, intent (in) :: n type (big_integer) :: b if (n < 0) then b = 0 else if (n >= nr_of_digits) then b = huge (b) else b % digit = 0 b % digit (n) = 1 end if end function big_base_to_power function big_plus_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i type (big_integer) :: bi type (big_integer) :: temp_big temp_big = i bi = b + temp_big end function big_plus_int function big_plus_big (x, y) result (bb) type (big_integer), intent (in) :: x, y type (big_integer) :: bb integer :: carry, temp_digit, n carry = 0 do n = 0, nr_of_digits temp_digit = & x % digit (n) + y % digit (n) + carry bb % digit (n) = modulo (temp_digit, base) carry = temp_digit / base end do if (bb % digit (nr_of_digits) /= 0 .or. & carry /= 0) then print *, "overflow adding two big integers" stop end if end function big_plus_big function big_minus_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i type (big_integer) :: bi type (big_integer) :: temp_big temp_big = i bi = b - temp_big end function big_minus_int function big_minus_big (x, y) result (bb) type (big_integer), intent (in) :: x, y type (big_integer) :: bb type (big_integer) :: temp_big integer :: n temp_big = x do n = 0, nr_of_digits - 1 bb % digit (n) = temp_big % digit (n) - y % digit (n) if (bb % digit (n) < 0) then bb % digit (n) = bb % digit (n) + base temp_big % digit (n + 1) = temp_big % digit (n + 1) - 1 end if end do if (temp_big % digit (nr_of_digits) < 0) then bb % digit = 0 else bb % digit (nr_of_digits) = 0 end if end function big_minus_big function big_times_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i type (big_integer) :: bi integer :: i0, i1, carry, n, temp_digit i0 = modulo (i, base) carry = 0 do n = 0, nr_of_digits temp_digit = b % digit (n) * i0 + carry bi % digit (n) = modulo (temp_digit, base) carry = temp_digit / base end do if (bi % digit (nr_of_digits) /= 0 .or. & carry /= 0) then print *, "overflow multiplying by an integer" stop end if if (i1 >= base) then i1 = i / base carry = 0 do n = 1, nr_of_digits temp_digit = b % digit (n-1) * i1 + bi % digit (n) + carry bi % digit (n) = modulo (temp_digit, base) carry = temp_digit / base end do if (bi % digit (nr_of_digits) /= 0 .or. & carry /= 0) then print *, "overflow multiplying by an integer" stop end if end if end function big_times_int function big_times_big (x, y) result (bb) type (big_integer), intent (in) :: x, y type (big_integer) :: bb type (big_integer) :: temp_big integer :: n bb % digit = 0 do n = nr_of_digits, 0, -1 if (x % digit (n) /= 0) then temp_big = y * (x % digit (n)) temp_big % digit = eoshift (temp_big % digit, -n) bb = bb + temp_big end if end do end function big_times_big function big_div_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i type (big_integer) :: bi integer :: n, temp_int, remainder if (i == 0) then bi = huge (bi) return end if remainder = 0 do n = nr_of_digits, 0, -1 temp_int = base * remainder + b % digit (n) bi % digit (n) = temp_int / i remainder = modulo (temp_int, i) end do end function big_div_int function big_div_big (x, y) result (bb) type (big_integer), intent (in) :: x, y type (big_integer) :: bb type (big_integer) :: high, low integer :: m, n if (x < y) then bb = 0 else if (y == 0) then bb = huge (y) else if (y == 1) then bb = x else do m = nr_of_digits, 0, -1 if (x % digit (m) > 0) then exit end if end do do n = nr_of_digits, 0, -1 if (y % digit (n) > 0) then exit end if end do high % digit = 0 if (m - n + 1 >= nr_of_digits) then high = huge (high) else high % digit (m - n + 1) = 1 end if low % digit = 0 low % digit (max(0, m - n - 1)) = 1 do bb = (high + low) / 2 if (x < bb * y) then high = bb else if ((bb + 1) * y <= x) then low = bb else exit end if end do end if end function big_div_big function modulo_big_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i integer :: bi integer :: n, remainder if (i==0) then bi = huge (bi) return end if remainder = 0 do n = nr_of_digits, 0, -1 remainder = modulo (base * remainder + b % digit (n), i) end do bi = remainder end function modulo_big_int function modulo_big_big (x, y) result (bb) type (big_integer), intent (in) :: x, y type (big_integer) :: bb if (y == 0) then bb = huge (bb) else bb = x - x / y * y end if end function modulo_big_big function big_eq_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base bi = b % digit (0) == i0 .and. & b % digit (1) == i1 .and. & all (b % digit (2 : nr_of_digits) == 0) end function big_eq_int function int_eq_big (i, b) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base bi = b % digit (0) == i0 .and. & b % digit (1) == i1 .and. & all (b % digit (2 : nr_of_digits) == 0) end function int_eq_big function big_eq_big (x, y) result (bb) type (big_integer), intent (in) :: x, y logical :: bb integer :: n bb = .true. do n = nr_of_digits, 0, -1 if (x % digit (n) /= y % digit (n)) then bb = .false. exit end if end do end function big_eq_big function big_ne_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base bi = b % digit (0) == i0 .and. & b % digit (1) == i1 .and. & all (b % digit (2 : nr_of_digits) == 0) bi = .not. bi end function big_ne_int function int_ne_big (i, b) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base bi = b % digit (0) == i0 .and. & b % digit (1) == i1 .and. & all (b % digit (2 : nr_of_digits) == 0) bi = .not. bi end function int_ne_big function big_ne_big (x, y) result (bb) type (big_integer), intent (in) :: x, y logical :: bb integer :: n bb = .true. do n = nr_of_digits, 0, -1 if (x % digit (n) /= y % digit (n)) then bb = .false. exit end if end do bb = .not. bb end function big_ne_big function big_le_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) <= i0) then bi = .true. else bi = .false. end if end function big_le_int function int_le_big (i, b) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) <= i0) then bi = .true. else bi = .false. end if end function int_le_big function big_le_big (x, y) result (bb) type (big_integer), intent (in) :: x, y logical :: bb integer :: n bb = .true. do n = nr_of_digits, 0, -1 if (x % digit (n) /= y % digit (n)) then bb = (x % digit (n) < y % digit (n)) exit end if end do end function big_le_big function big_gt_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) <= i0) then bi = .true. else bi = .false. end if bi = .not. bi end function big_gt_int function int_gt_big (i, b) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) <= i0) then bi = .true. else bi = .false. end if bi = .not. bi end function int_gt_big function big_gt_big (x, y) result (bb) type (big_integer), intent (in) :: x, y logical :: bb integer :: n bb = .true. do n = nr_of_digits, 0, -1 if (x % digit (n) /= y % digit (n)) then bb = (x % digit (n) < y % digit (n)) exit end if end do bb = .not. bb end function big_gt_big function big_lt_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) < i0) then bi = .true. else bi = .false. end if end function big_lt_int function int_lt_big (i, b) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) < i0) then bi = .true. else bi = .false. end if end function int_lt_big function big_lt_big (x, y) result (bb) type (big_integer), intent (in) :: x, y logical :: bb integer :: n bb = .false. do n = nr_of_digits, 0, -1 if (x % digit (n) /= y % digit (n)) then bb = (x % digit (n) < y % digit (n)) exit end if end do end function big_lt_big function big_ge_int (b, i) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) < i0) then bi = .true. else bi = .false. end if bi = .not. bi end function big_ge_int function int_ge_big (i, b) result (bi) type (big_integer), intent (in) :: b integer, intent (in) :: i logical :: bi integer :: i0, i1 i0 = modulo (i, base) i1 = i / base if (any (b % digit (2 : nr_of_digits) /= 0)) then bi = .false. else if (b % digit (1) > i1) then bi = .false. else if (b % digit (1) == i1 .and. & b % digit (0) < i0) then bi = .true. else bi = .false. end if bi = .not. bi end function int_ge_big function big_ge_big (x, y) result (bb) type (big_integer), intent (in) :: x, y logical :: bb integer :: n bb = .false. do n = nr_of_digits, 0, -1 if (x % digit (n) /= y % digit (n)) then bb = (x % digit (n) < y % digit (n)) exit end if end do bb = .not. bb end function big_ge_big function huge_big (b) result (hb) type (big_integer), intent (in) :: b type (big_integer) :: hb hb % digit = base - 1 hb % digit (nr_of_digits) = 0 end function huge_big function sqrt_big (b) result (sb) type (big_integer), intent (in) :: b type (big_integer) :: sb type (big_integer) :: old_sqrt_big, new_sqrt_big integer :: i, n n = -1 do i = nr_of_digits, 0, -1 if (b % digit (i) /= 0) then n = i exit end if end do if (n == -1) then sb = 0 else if (n == 0) then sb = int (sqrt (real (b % digit (0)))) else old_sqrt_big = 0 if (modulo (n, 2) == 0) then old_sqrt_big % digit (n / 2) = int (sqrt (real (b % digit (n)))) else old_sqrt_big % digit ((n - 1) / 2) = & int (sqrt (real (base * b % digit (n) + b % digit (n-1)))) end if do new_sqrt_big = (old_sqrt_big + b / old_sqrt_big) / 2 if (new_sqrt_big == old_sqrt_big .or. & new_sqrt_big == old_sqrt_big + 1 .or. & new_sqrt_big == 0) then exit else old_sqrt_big = new_sqrt_big end if end do sb = old_sqrt_big end if end function sqrt_big recursive function big_power_int (b, i) & result (big_power_int_result) type (big_integer), intent (in) :: b integer, intent (in) :: i type (big_integer) :: big_power_int_result type (big_integer) :: temp_big if (i <= 0) then big_power_int_result = 1 else temp_big = big_power_int (b, i / 2) if (modulo (i, 2) == 0) then big_power_int_result = temp_big * temp_big else big_power_int_result = temp_big * temp_big * b end if end if end function big_power_int function prime (b) result (pb) type (big_integer), intent (in) :: b logical :: pb type (big_integer) :: s, div if (b <= 1) then pb = .false. else if (b == 2) then pb = .true. else if (modulo (b, 2) == 0) then pb = .false. else pb = .true. s = sqrt (b) div = 3 do if (.not. s <= div) then exit end if if (modulo (b, div) == 0) then pb = .false. exit end if div = div + 2 end do end if end function prime subroutine print_big (b) type (big_integer), intent (in) :: b type (big_integer) :: temp_big integer :: n, remainder character (len=1), dimension (nr_of_decimal_digits) :: & decimal_digits character (len = 10), parameter :: digit_chars = "0123456789" temp_big = b decimal_digits = " " do n = 1, nr_of_decimal_digits if (all (temp_big % digit == 0)) then exit end if remainder = modulo (temp_big, 10) + 1 temp_big = temp_big / 10 decimal_digits (n) = digit_chars (remainder:remainder) end do if (n == 1) then write (unit = *, fmt = "(a)", advance = "no") "0" else do n = n - 1, 1, -1 write (unit = *, fmt = "(a)", advance = "no") decimal_digits (n) end do end if end subroutine print_big subroutine print_big_base (b) type (big_integer), intent (in) :: b integer :: n print *, "base: ", base do n = nr_of_digits, 1, -1 if (b % digit (n) /= 0) then exit end if end do print "(10i9)", b % digit (n:0:-1) end subroutine print_big_base subroutine print_factors (b) type (big_integer), intent (in) :: b type (big_integer) :: temp_b, f, sqrt_b temp_b = b f = 2 sqrt_b = sqrt (b) do if (modulo (temp_b, f) == 0) then write (unit = *, fmt = "(a)", advance="no") "2 " temp_b = temp_b / 2 else exit end if end do f = 3 do if (temp_b == 1) then exit end if if (sqrt_b < f) then call print_big (temp_b) write (unit = *, fmt = "(a)", advance="no") " " exit end if do if (modulo (temp_b, f) == 0) then call print_big (f) write (unit = *, fmt = "(a)", advance="no") " " temp_b = temp_b / f sqrt_b = sqrt (temp_b) else exit end if end do f = f + 2 end do end subroutine print_factors end module big_integers_module program test_big use big_integers_module type (big_integer) :: b1 b1 = "1234567654321" call print_big (b1) print * call print_factors (b1) print * end program test_big
Back to F Example Codes Page
Back to F Homepage