Previous | Table of Contents | Next |
The name for the subroutine big_gets_char was picked because it converts a character string to a big integer. This is like intrinsic assignment that converts an integer to a real value when necessary. Indeed, it is possible to use the assignment statement to do the conversion from character to big integer. It is done by extending assignment. The following interface block is placed in the module big_integers to indicate that the module procedure big_gets_char is to be used to extend assignment to the case where the variable on the left side of the assignment is a big integer and the expression on the right side is a character expression:
public :: assignment (=) private :: big_gets_char interface assignment (=) module procedure big_gets_char end interface
Here is what the module big_integers looks like so far:
module big_integers_module integer, parameter, private :: nr_of_decimal_digits = 100 type, public :: big_integer private integer, dimension (0 : nr_of_digits) :: digit end type big_integer interface assignment (=) module procedure big_gets_char end interface public :: assignment (=) private :: big_gets_char contains subroutine big_gets_char (b, c) . . . end subroutine big_gets_char subroutine print_big (b) . . . end subroutine print_big end module big_integers_module
Any user of the module can use the assignment statement instead of calling a subroutine, which makes the program a lot easier to understand:
program test_big_1 use big_integers_module type (big_integer) :: b1 b1 = 71234567890987654321 call print_big (b1) b1 = 123456789+987654321 ! Will be huge(b) = 99999 call print_big (b1) end program test_big_1
With conversion from character strings to big integers using the assignment statement, there is no need to have the subroutine big_gets_char available. It is declared private.
1.2.18.2. Extending Intrinsic Functions to Big Integers
Many of the Fortran intrinsic functions manipulate numeric values, and it is reasonable to extend some of them, such as modulo and sqrt, to have big integer arguments. This is done by writing an interface block and the function to do the computation. This is illustrated by extending the intrinsic function huge so that when given a big integer as argument, it returns the largest possible big integer. This function is tested by the program test_big_2:
module big_integers_module intrinsic huge public :: huge . . . interface huge module procedure huge_big end interface . . . contains . . . function huge_big (b) result (huge_big_result) type (big_integer), intent (in) :: b type (big_integer) :: huge_big_result huge_big_result % digit (0 : nr_of_digits - 1) = 9 huge_big_result % digit (nr_of_digits) = 0 end function huge_big . . . end module big_integers_module program test_big_2 use big_integers_module type (big_integer) :: b1 call print_big (huge (b1)) end program test_big_2
1.2.18.3. Adding Big Integers
Now that we can assign to a big integer variable and print its value, it would be nice to be able to perform some computations with big integers. Addition can be done with a function that adds just like we do with pencil and paper, adding two digits at a time and keeping track of any carry-over, starting with the rightmost digits. The function big_plus_big does this:
function big_plus_big (x, y) result (big_plus_big_result) type (big_integer), intent (in) :: x, y type (big_integer) :: big_plus_big_result integer :: carry, temp_sum, n carry = 0 do n = 0, nr_of_digits temp_sum = x % digit (n) + y % digit (n) + carry big_plus_big_result % digit (n) = modulo (temp_sum, 10) carry = temp_sum / 10 end do if (big_plus_big_result % digit(nr_of_digits) /= 0 & .or. carry /= 0) then big_plus_big_result = huge (big_plus_big_result) end if end function big_plus_big
We now extend the meaning of addition to our own newly defined type, big_integer. This is done with another interface block, this time with the keyword operator, followed by the operator being extended. The + operator is public, but the subroutine big_plus_big is private:
interface operator (+) module procedure big_plus_big end interface
The use of the + operator to add two big integers is tested by the program test_big_3:
program test_big_3 use big_integers_module type (big_integer) :: b1, b2 b1 = 1234567890987654321 b2 = 9876543210123456789 call print_big (b1 + b2) end program test_big_3
The value printed by this program is
11111111101111111110
Previous | Table of Contents | Next |