Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
95
Task/Modular-arithmetic/Fortran/modular-arithmetic-1.f
Normal file
95
Task/Modular-arithmetic/Fortran/modular-arithmetic-1.f
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
module modular_arithmetic
|
||||
implicit none
|
||||
|
||||
type :: modular
|
||||
integer :: val
|
||||
integer :: modulus
|
||||
end type modular
|
||||
|
||||
interface operator(+)
|
||||
module procedure modular_modular_add
|
||||
module procedure modular_integer_add
|
||||
end interface operator(+)
|
||||
|
||||
interface operator(**)
|
||||
module procedure modular_integer_pow
|
||||
end interface operator(**)
|
||||
|
||||
contains
|
||||
|
||||
function modular_modular_add (a, b) result (c)
|
||||
type(modular), intent(in) :: a
|
||||
type(modular), intent(in) :: b
|
||||
type(modular) :: c
|
||||
|
||||
if (a%modulus /= b%modulus) error stop
|
||||
c%val = modulo (a%val + b%val, a%modulus)
|
||||
c%modulus = a%modulus
|
||||
end function modular_modular_add
|
||||
|
||||
function modular_integer_add (a, i) result (c)
|
||||
type(modular), intent(in) :: a
|
||||
integer, intent(in) :: i
|
||||
type(modular) :: c
|
||||
|
||||
c%val = modulo (a%val + i, a%modulus)
|
||||
c%modulus = a%modulus
|
||||
end function modular_integer_add
|
||||
|
||||
function modular_integer_pow (a, i) result (c)
|
||||
type(modular), intent(in) :: a
|
||||
integer, intent(in) :: i
|
||||
type(modular) :: c
|
||||
|
||||
! One cannot simply use the integer ** operator and then compute
|
||||
! the least residue, because the integers will overflow. Let us
|
||||
! instead use the right-to-left binary method:
|
||||
! https://en.wikipedia.org/w/index.php?title=Modular_exponentiation&oldid=1136216610#Right-to-left_binary_method
|
||||
|
||||
integer :: modulus
|
||||
integer :: base
|
||||
integer :: exponent
|
||||
|
||||
modulus = a%modulus
|
||||
exponent = i
|
||||
|
||||
if (modulus < 1) error stop
|
||||
if (exponent < 0) error stop
|
||||
|
||||
c%modulus = modulus
|
||||
if (modulus == 1) then
|
||||
c%val = 0
|
||||
else
|
||||
c%val = 1
|
||||
base = modulo (a%val, modulus)
|
||||
do while (exponent > 0)
|
||||
if (modulo (exponent, 2) /= 0) then
|
||||
c%val = modulo (c%val * base, modulus)
|
||||
end if
|
||||
exponent = exponent / 2
|
||||
base = modulo (base * base, modulus)
|
||||
end do
|
||||
end if
|
||||
end function modular_integer_pow
|
||||
|
||||
end module modular_arithmetic
|
||||
|
||||
! If one uses the extension .F90 instead of .f90, then gfortran will
|
||||
! pass the program through the C preprocessor. Thus one can write f(x)
|
||||
! without considering the type of the argument
|
||||
#define f(x) ((x)**100 + (x) + 1)
|
||||
|
||||
program modular_arithmetic_task
|
||||
use, intrinsic :: iso_fortran_env
|
||||
use, non_intrinsic :: modular_arithmetic
|
||||
implicit none
|
||||
|
||||
type(modular) :: x, y
|
||||
|
||||
x = modular(10, 13)
|
||||
y = f(x)
|
||||
|
||||
write (*, '(" modulus 13: ", I0)') y%val
|
||||
write (*, '("floating point: ", E55.50)') f(10.0_real64)
|
||||
|
||||
end program modular_arithmetic_task
|
||||
Loading…
Add table
Add a link
Reference in a new issue