MathClass.f90 Source File


Contents

Source Code


Source Code

module MathClass
    use, intrinsic :: iso_fortran_env
	!use OouraFFT
	use StringClass
	implicit none
	

	integer(int32) :: i_i = 0
	integer(int32) :: j_j = 0
	integer(int32) :: k_k = 0

	logical :: true = .True.
	logical :: False = .False.
	!integer(int32) :: i_i = 0



	type :: Math_
		real(real64) :: PI = 3.141592653589793d0
		real(real64) :: E  = 2.718281828459045d0
		complex(kind(0d0))	 :: i = (0.0d0, 1.0d0)
		complex(kind(0d0))	 :: j = (0.0d0, 1.0d0)
	end type


	type :: Real64Ptr_
    	real(real64), pointer :: ptr
  	end type Real64Ptr_

	integer(int32),parameter :: complex64 = real64
	!real(real64) :: pi=3.141592653589793238d0
	!
	interface nchoosek
		module procedure comb
	end interface

	interface choose
		module procedure comb
	end interface
	
	interface fact
		module procedure factorialInt32, factorialReal64
	end interface


	interface factorial
		module procedure factorialInt32, factorialReal64
	end interface factorial

	interface heapsort
		module procedure :: heapsortInt32, heapsortReal64,heapsortReal32
	end interface

	interface str
		module procedure fstring_Int, fstring_Real,fstring_Real32, &
			fstring_complex, fstring_Int_len, fstring_Real_len, fstring_logical, fstring_String,stringFromChar
	end interface str

    interface fstring
        module procedure fstring_Int, fstring_Real, fstring_Int_len, fstring_Real_len, fstring_logical
	end interface fstring

	interface input
		module procedure input_Int,input_Real,input_Real32,input_Complex,input_IntVec,&
			input_RealVec,input_IntArray,input_RealArray,input_String,input_logical
	end interface input
	
	interface zeroif
		module procedure zeroif_Int,zeroif_Real
	end interface zeroif

	interface removeWord
		module procedure removeWord_String 
	end interface 

	interface radian
		module procedure radianreal32,radianreal64, radianint
	end interface

	interface array
		module procedure arrayDim1Real64,arrayDim2Real64,arrayDim3Real64
	end interface

	
contains
! ###############################################
recursive function FFT(x) result(hatx)
	complex(kind(0d0))	,intent(in) :: x(:)
	complex(kind(0d0))	,allocatable :: hatx(:),W(:),L(:),R(:)
	real(real64),allocatable :: a(:), wo(:)
	integer(int32),allocatable :: ip(:)
	integer(int32) :: N, i, itr,isgn
	integer(int32),allocatable :: k(:)
	type(Math_) :: Math

	!!! call Ooura-FFT
	!n = size(x)/2
	!allocate(a(0:2*n-1) )
	!allocate(wo(0:2*n-1) )
	!a(0:2*n-1) = x(1:2*n)
	!isgn = n
	!call cdft(2*n,isgn,a(0:2*n-1),ip,wo(0:n/2-1) )
	!hatx = a
	!
	!return
	!!! 
	N = size(x)
	allocate(hatx(N))

	hatx(:) = 0.0d0
	allocate(k(N/2) )
	allocate(W(N/2) )
	allocate(L(N/2) )
	allocate(R(N/2) )
	
	do i=1,size(k)
		k(i) = i-1
		!print *, exp(-1*Math%i * 2.0d0* Math%PI * k(i)/dble(N))
		W(i) = exp(-1*Math%i * 2.0d0* Math%PI * k(i) /dble(N) )
	enddo
	
	if(N==2)then
		! butterfly operation
		hatx(1) = x(1) + x(2)
		hatx(2) = x(1) - x(2)
		return
	endif
	
	if(N>=4)then
		itr=0
		do i=1, N, 2
			itr=itr+1
			
			if(itr > size(L) )then
				exit
			endif
			L(itr) = x(i)
		enddo 

		itr=0
		do i=2, N, 2
			itr=itr+1
			if(itr > size(R) )then
				exit
			endif
			R(itr) = x(i)
		enddo
		
		L = FFT(L)
		R = FFT(R)
		
		do i=1,N/2
			hatx(i) = L(i) + W(i)*R(i)
		enddo
		do i=N/2+1, N
			if(i-N/2 > size(L) )then
				exit
			endif
			hatx(i) = L(i-N/2) - W(i-N/2)*R(i-N/2)
		enddo
		return
	endif
end function
! ###############################################
function IFFT(x) result(hatx)
	complex(kind(0d0))	,intent(in) :: x(:)
	complex(kind(0d0))	,allocatable :: hatx(:)
	type(Math_) :: Math

	hatx = IFFT_core(x)

	hatx = 1.0d0/dble(size(x))*hatx
	
end function

! ###############################################
recursive function IFFT_core(x) result(hatx)
	complex(kind(0d0))	,intent(in) :: x(:)
	complex(kind(0d0))	,allocatable :: hatx(:),W(:),L(:),R(:)
	real(real64),allocatable :: a(:), wo(:)
	integer(int32),allocatable :: ip(:)
	integer(int32) :: N, i, itr,isgn
	integer(int32),allocatable :: k(:)
	type(Math_) :: Math

	!!! call Ooura-FFT
	!n = size(x)/2
	!allocate(a(0:2*n-1) )
	!allocate(wo(0:2*n-1) )
	!a(0:2*n-1) = x(1:2*n)
	!isgn = n
	!call cdft(2*n,isgn,a(0:2*n-1),ip,wo(0:n/2-1) )
	!hatx = a
	!
	!return
	!!! 
	N = size(x)
	allocate(hatx(N))

	hatx(:) = 0.0d0
	allocate(k(N/2) )
	allocate(W(N/2) )
	allocate(L(N/2) )
	allocate(R(N/2) )
	
	do i=1,size(k)
		k(i) = i-1
		!print *, exp(-1*Math%i * 2.0d0* Math%PI * k(i)/dble(N))
		W(i) = exp(Math%i * 2.0d0* Math%PI * k(i) /dble(N) )
	enddo
	
	if(N==2)then
		! butterfly operation
		hatx(1) = x(1) + x(2)
		hatx(2) = x(1) - x(2)
		return
	endif
	
	if(N>=4)then
		itr=0
		do i=1, N, 2
			itr=itr+1
			
			if(itr > size(L) )then
				exit
			endif
			L(itr) = x(i)
		enddo 

		itr=0
		do i=2, N, 2
			itr=itr+1
			if(itr > size(R) )then
				exit
			endif
			R(itr) = x(i)
		enddo
		
		L = IFFT_core(L)
		R = IFFT_core(R)
		
		do i=1,N/2
			hatx(i) = L(i) + W(i)*R(i)
		enddo
		do i=N/2+1, N
			if(i-N/2 > size(L) )then
				exit
			endif
			hatx(i) = L(i-N/2) - W(i-N/2)*R(i-N/2)
		enddo
		return
	endif


end function
! ###############################################

! ###############################################
function arrayDim1Real64(size1) result(ret)
	integer(int32),intent(in) :: size1
	real(real64),allocatable :: ret(:)

	allocate(ret(size1) )

	ret(:) = 0.0d0

end function
! ###############################################


! ###############################################
function arrayDim2Real64(size1,size2) result(ret)
	integer(int32),intent(in) :: size1,size2
	real(real64),allocatable :: ret(:,:)

	allocate(ret(size1,size2) )

	ret(:,:) = 0.0d0


end function
! ###############################################


! ###############################################
function arrayDim3Real64(size1,size2,size3) result(ret)
	integer(int32),intent(in) :: size1,size2,size3
	real(real64),allocatable :: ret(:,:,:)

	allocate(ret(size1,size2,size3) )

	ret(:,:,:) = 0.0d0


end function
! ###############################################

! ###############################################
function radianreal32(deg) result(ret)
	real(real32),intent(in) :: deg
	real(real64) :: ret
	ret = deg/180.0d0*3.1415926535d0
end function
! ###############################################

! ###############################################
function radianreal64(deg) result(ret)
	real(real64),intent(in) :: deg
	real(real64) :: ret
	ret = deg/180.0d0*3.1415926535d0
end function
! ###############################################

! ###############################################
function radianint(deg) result(ret)
	integer(int32),intent(in) :: deg
	real(real64) :: ret
	ret = dble(deg)/180.0d0*3.1415926535d0
end function
! ###############################################

! ###############################################
function degrees(rad) result(ret)
	real(real64),intent(in) :: rad
	real(real64) :: ret
	ret = rad/3.1415926535d0*180.0d0
end function
! ###############################################


!########################################
function norm(vec) result(a)
	real(real64),intent(in)::vec(:)
	integer(int32) :: n
	real(real64) :: a

	n=size(vec)
	a=dsqrt(dot_product(vec,vec) )

end function
!########################################





!########################################
pure function SearchNearestValueID(Vector,x)  result(id)
	real(real64),intent(in) :: Vector(:)
	real(real64),intent(in) :: x
	integer(int32) :: id,i
	
	id = 1
	do i=1,size(vector)
		if( abs(vector(id)-x) > abs(vector(i)-x) )then
			id = i
			cycle
		endif
	enddo

end function
!########################################


!########################################
function SearchNearestValueIDs(Vector,x,num)  result(id)
	real(real64),intent(in) :: Vector(:)
	real(real64),intent(in) :: x
	integer(int32),intent(in)  :: num
	integer(int32) :: id(num),i,j

	id(:) = 1		
	do j=1,num
		do i=1,size(vector)
			if(j>=2 )then
				if(abs(minval(id(1:j-1) - i ))==0) cycle
			endif
			if( abs(vector(id(j) )-x) > abs(vector(i)-x) )then
				id(j) = i
				cycle
			endif
		enddo
	enddo
end function
!########################################

!########################################
function SearchNearestValue(Vector,x)  result(val)
	real(real64),intent(in) :: Vector(:)
	real(real64),intent(in) :: x
	integer(int32) :: id, i
	real(real64) :: val
	
	id = 1
	do i=1,size(vector)
		if( abs(vector(id)-x) > abs(vector(i)-x) )then
			id = i
			cycle
		endif
	enddo

	val = vector(id)
end function
!########################################


!########################################
function SearchNearestCoord(Array,x)  result(id)
	real(real64),intent(in) :: Array(:,:)
	real(real64),intent(in) :: x(:)
	integer(int32),allocatable::xr(:)

	integer(int32) :: i,id,n,m,norm,tr_norm

	n=size(Array,1)
	m=size(Array,2)
	if(m/=size(x) )then
		stop "ERROR :: SearchNearestCoord >> size(Array,2) should be =size(x)"
	endif

	allocate(xr(m) )
	do i=1,n
		xr(:)=Array(i,:)
		tr_norm=dot_product(xr-x,xr-x)
		if(i==1)then
			norm=tr_norm
			id  =i
		else
			if(norm > tr_norm)then
				norm=tr_norm
				id  =i
			else
				cycle
			endif
		endif
	enddo


	
end function
!########################################

!##################################################
function SearchIDIntVec(Vec,val) result(id_)
	integer(int32),intent(in) :: Vec(:)
	integer(int32),intent(in) :: val

	integer(int32) :: i,id_

	do i=1,size(Vec)
		if(Vec(i)==val )then
			id_=i
			return
		endif
	enddo

end function
!##################################################

!##################################################
subroutine heapsortReal64(n,array,val)
  	integer(int32),intent(in) :: n
  	real(real64),intent(inout) :: array(1:n)! rearrange order by this array
	real(real64),optional,intent(inout) :: val(1:n) ! linked data
	real(real64) :: t_real
  	integer(int32) ::i,k,j,l
  	real(real64) :: t
  
  	if(n.le.0)then
  		write(6,*)"Error, at heapsort"; stop
  	endif
  	if(n.eq.1)return

	l=n/2+1
	k=n
	do while(k.ne.1)
	    if(l.gt.1)then
	        l=l-1
	        t=array(L)
			if(present(val) )then
				t_real=val(L)
			endif
	    else
	        t=array(k)
			if(present(val) )then
				t_real=val(k)
			endif

	        array(k)=array(1)
			if(present(val) )then			
				val(k) = val(1)
			endif

	        k=k-1
	        if(k.eq.1) then
	           	array(1)=t
				   if(present(val) )then
						val(1) = t_real
				   endif
	        	exit
	        endif
	    endif
	    i=l
	    j=l+l
	    do while(j.le.k)
	        if(j.lt.k)then
	           	if(array(j).lt.array(j+1))j=j+1

	        endif
	        if (t.lt.array(j))then
	        	array(i)=array(j)
				if(present(val) )then
				val(i)=val(j)
				endif
	        	i=j
	        	j=j+j
	        else
	        	j=k+1
	        endif
	    enddo
	 	array(i)=t
		 if(present(val) )then
		 val(i)=t_real
		 endif
  	enddo

end subroutine heapsortReal64

!##################################################
subroutine heapsortReal32(n,array,val)
	integer(int32),intent(in) :: n
	real(real32),intent(inout) :: array(1:n)! rearrange order by this array
  real(real32),optional,intent(inout) :: val(1:n) ! linked data
  real(real32) :: t_real
	integer(int32) ::i,k,j,l
	real(real32) :: t

	if(n.le.0)then
		write(6,*)"Error, at heapsort"; stop
	endif
	if(n.eq.1)return

  l=n/2+1
  k=n
  do while(k.ne.1)
	  if(l.gt.1)then
		  l=l-1
		  t=array(L)
		  if(present(val) )then
			  t_real=val(L)
		  endif
	  else
		  t=array(k)
		  if(present(val) )then
			  t_real=val(k)
		  endif

		  array(k)=array(1)
		  if(present(val) )then			
			  val(k) = val(1)
		  endif

		  k=k-1
		  if(k.eq.1) then
				 array(1)=t
				 if(present(val) )then
					  val(1) = t_real
				 endif
			  exit
		  endif
	  endif
	  i=l
	  j=l+l
	  do while(j.le.k)
		  if(j.lt.k)then
				 if(array(j).lt.array(j+1))j=j+1

		  endif
		  if (t.lt.array(j))then
			  array(i)=array(j)
			  if(present(val) )then
			  val(i)=val(j)
			  endif
			  i=j
			  j=j+j
		  else
			  j=k+1
		  endif
	  enddo
	   array(i)=t
	   if(present(val) )then
	   val(i)=t_real
	   endif
	enddo

end subroutine heapsortReal32



!##################################################
subroutine heapsortInt32(n,array,val)
	integer(int32),intent(in) :: n
	integer(int32),intent(inout) :: array(1:n)! rearrange order by this array
  real(real64),optional,intent(inout) :: val(1:n) ! linked data
  real(real64) :: t_real
	integer(int32) ::i,k,j,l
	integer(int32) :: t

	if(n.le.0)then
		write(6,*)"Error, at heapsort"; stop
	endif
	if(n.eq.1)return

  l=n/2+1
  k=n
  do while(k.ne.1)
	  if(l.gt.1)then
		  l=l-1
		  t=array(L)
		  if(present(val) )then
			  t_real=val(L)
		  endif
	  else
		  t=array(k)
		  if(present(val) )then
			  t_real=val(k)
		  endif

		  array(k)=array(1)
		  if(present(val) )then			
			  val(k) = val(1)
		  endif

		  k=k-1
		  if(k.eq.1) then
				 array(1)=t
				 if(present(val) )then
					  val(1) = t_real
				 endif
			  exit
		  endif
	  endif
	  i=l
	  j=l+l
	  do while(j.le.k)
		  if(j.lt.k)then
				 if(array(j).lt.array(j+1))j=j+1

		  endif
		  if (t.lt.array(j))then
			  array(i)=array(j)
			  if(present(val) )then
			  val(i)=val(j)
			  endif
			  i=j
			  j=j+j
		  else
			  j=k+1
		  endif
	  enddo
	   array(i)=t
	   if(present(val) )then
	   val(i)=t_real
	   endif
	enddo

end subroutine heapsortInt32

!==========================================================
!calculate cross product
!---------------------------
function cross_product(a,b) result (c)
	real(real64), intent(in) :: a(:),b(:)
	real(real64), allocatable :: c(:)
  
    if(size(a) /= 3 .or. size(b)/= 3 ) then
        stop  "wrong number on size a, b"
    endif
 
    allocate(c(size(a,1)))
  	if(size(c,1)==3) then
     	c(1) = a(2)*b(3) - a(3)*b(2)
     	c(2) = a(3)*b(1) - a(1)*b(3)
     	c(3) = a(1)*b(2) - a(2)*b(1)
  	else
      	stop "wrong number at cross_product"
  	endif
  
end function cross_product
!=========================================================
!calculate diadic
!----------------------
function diadic(a,b) result(c)
  real(real64), intent(in) :: a(:), b(:)
	real(real64), allocatable :: c(:,:)
	
	integer(int32) n,i,j
	   
	allocate(c(size(a),size(b) ) )
	do i=1,size(a)
		do j=1,size(b)
			c(i,j)=a(i)*b(j)		
		enddo
	enddo

end function diadic	
!==========================================================
!=========================================================
!calculate diadic
!----------------------
function tensor_product(a,b) result(c)
	real(real64), intent(in) :: a(:), b(:)
	  real(real64), allocatable :: c(:,:)
	  
	  integer(int32) n,i,j
		 
	  allocate(c(size(a),size(b) ) )
	  do i=1,size(a)
		  do j=1,size(b)
			  c(i,j)=a(i)*b(j)		
		  enddo
	  enddo
  
  end function tensor_product	
  !==========================================================
!calculate gz
!--------------
subroutine calcgz(x2,x11,x12,nod_coord,gzi)
	real(real64), intent(in) :: nod_coord(:,:)
	real(real64),intent(out) :: gzi
	integer(int32),intent(in):: x2,x11,x12
		real(real64) l
		real(real64),allocatable::avec(:)

		allocate(avec(2))
		l = dot_product( nod_coord(x12,1:2) - nod_coord(x11,1:2), &
			nod_coord(x12,1:2) - nod_coord(x11,1:2) ) 
		l=l**(1.0d0/2.0d0)
	 
		avec(1:2) = ( nod_coord(x12,1:2) - nod_coord(x11,1:2)   )/l
		
		if(l==0.0d0)then
			print *, "calcgz l=0"
			gzi=0.0d0
		else
			gzi=1.0d0/l*dot_product( nod_coord(x2,1:2) -nod_coord(x11,1:2),avec(1:2) )
		endif

	 deallocate(avec)
	 
end subroutine calcgz
!==========================================================
function arg(comp) result(theta)
	complex,intent(in) :: comp
	real(real64) :: theta,re,im
	real(real64) ::pi=3.141592653589793d0

	re = dble(real(comp) )
	im = dble(aimag(comp) )

	if(re>0.0d0 )then
		theta = atan(im/re)
	elseif(re<0.0d0 .and. im>=0.0d0)then
		theta = atan(im/re+pi)
	elseif(re<0.0d0 .and. im<0.0d0)then
		theta = atan(im/re-pi)
	elseif(re==0.0d0 .and. im>0.0d0)then
		theta = pi/2.0d0
	elseif(re==0.0d0 .and. im<0.0d0)then
		theta = -pi/2.0d0
	else
		print *, "arg :: indeterminate"
		stop 
	endif


end function
!==========================================================


function cubic_equation(a,b,c,d) result(x)
	real(real64),intent(in) :: a,b,c,d
	real(real64) :: x(3),theta
	real(real64) ::Deq,A_,B_,C_,p,q
	real(real64) ::pi=3.141592653589793d0
	complex  :: comp
	!https://qiita.com/yotapoon/items/42b1749b69c264d6f486

	A_ = b/a
	B_ = c/a
	C_ = d/a
	p = B_ - A_*A_/3.0d0
	q = 2.0d0*A_*A_*A_/27.0d0 - A_*B_/3.0d0 + C_
	Deq = q*q/4.0d0 + p*p*p/27.0d0
	
	if(Deq > 0.0d0)then
		print *, "D > 0 :: not implemented now."
	elseif(Deq==0)then
		print *, "D == 0 "
		x(1) = -2.0d0*(p/2.0d0)**(3)
		x(2) = (p/2.0d0)**(3)
		x(3) = (p/2.0d0)**(3)
		return
	else
		print *, "D < 0 "
		comp = cmplx(-q/2.0d0, sqrt(-Deq) )
		theta=arg(comp)
		x(1) = 2.0d0*sqrt(-p/3.0d0)*cos(theta)
		x(2) = 2.0d0*sqrt(-p/3.0d0)*cos( (theta+2.0d0*pi)/3.0d0 )
		x(3) = 2.0d0*sqrt(-p/3.0d0)*cos( (theta+4.0d0*pi)/3.0d0 )
	endif


end function

!==========================================================
subroutine eigen_2d(Amat,eigenvector)
	real(real64),intent(in)::Amat(:,:)
	real(real64),allocatable,intent(inout)::eigenvector(:,:)
	real(real64)::b,c,phy,eigenvalue(2)
	integer(int32) i,j
	
	eigenvalue=array(size(Amat,1) )
	eigenvector=array(size(Amat,1),size(Amat,1))
	
	b=-1.0d0*(Amat(1,1)+Amat(2,2))
	c=Amat(1,1)*Amat(2,2)-Amat(1,2)*Amat(1,2)
	
	if(Amat(1,2)/=Amat(2,1) )then
		 stop "input matrice is not symmetric"
	endif
	
	do i=1,2
		eigenvalue(i)=(-1.0d0*b+((-1.0d0)**dble(i))*(b*b-4.0d0*c)**(1.0d0/2.0d0))*(0.50d0)
	enddo
	
	do i=1,2
		if(Amat(1,2)==0 )then
			cycle
		elseif(Amat(1,2)/=0 )then
			phy=atan( (eigenvalue(i)-Amat(1,1))/Amat(1,2) ) 
			
			do j=1,2
				eigenvector(i,1:2)=(/cos(phy),sin(phy)/)
			enddo
		endif
	enddo
	
	do i=1,2
		eigenvector(i,:)=eigenvalue(i)*eigenvector(i,:)
	enddo
end subroutine eigen_2d
!==========================================================
function signmm(a) result(b)
	real(real64),intent(in)::a
	real(real64) b
	
	if(a>0)then
		b=1.0d0
	elseif(a<0)then
		b=-1.0d0
	elseif(a==0)then
		b=0.0d0
	else
		stop "ERROR: Invalid real(real64) in function_signm"
	endif
	
end function signmm 
!==========================================================

! ################################################################
! From 数値計算のためのFortran90/95プログラミング入門 単行本(ソフトカバー) –
! This function is not presented with GPL or any licenses.
! this function will be replaced by LAPACK.

recursive function det_mat(a,n) result(det)
  	integer(int32), intent(in) :: n
  	real(real64), intent(in) :: a(n, n)
  	real(real64) det, b(n-1, n-1)
  	integer(int32) i
	if (n > 1) then
		det = 0.0d0
		do i = 1, n
		  	b(1:i-1, 1:n-1) = a(1:i-1, 2:n)
		  	b(i:n-1, 1:n-1) = a(i+1:n, 2:n)
		  	det = det + (-1.0d0) ** (i + 1) &
			* a(i, 1) * det_mat(b, n-1)
		
		enddo
	else
		det = a(1,1)
	endif
end function det_mat
!=====================================================================================

!==========================================================
recursive function det(a,n) result(det_v)
  	integer(int32), intent(in) :: n
  	real(real64), intent(in) :: a(n, n)
  	real(real64) det_v, b(n-1, n-1)
  	integer(int32) i
	if (n > 1) then
		det_v = 0.0d0
		do i = 1, n
		  	b(1:i-1, 1:n-1) = a(1:i-1, 2:n)
		  	b(i:n-1, 1:n-1) = a(i+1:n, 2:n)
		  	det_v = det_v + (-1.0d0) ** (i + 1) &
			* a(i, 1) * det(b, n-1)
		
		enddo
	else
		det_v = a(1,1)
	endif
end function det
!=====================================================================================
subroutine trans_rank_2(A,A_T)
	real(real64),intent(in)::A(:,:)
	real(real64),allocatable,intent(out)::A_T(:,:)
	integer(int32) n,m,i,j
	
	n=size(A,1)
	m=size(A,2)
	if(.not. allocated(A_T) )allocate(A_T(m,n))
	
	do i=1,n
	  	do j=1, m
		  	A_T(j,i)=A(i,j)
	  	enddo
	enddo
	
 end subroutine trans_rank_2
!================================================================================== 
function trans1(A) result(A_T)
	real(real64),intent(in)::A(:)
	real(real64),allocatable::A_T(:,:)
	integer(int32) n,m,i,j
	
	n=size(A)
	if(.not. allocated(A_T) )allocate(A_T(1,n))
	
	do i=1,n
		A_T(1,i)=A(i)
	enddo
	
 end function trans1
!==================================================================================    
function trans2(A) result(A_T)
	real(real64),intent(in)::A(:,:)
	real(real64),allocatable::A_T(:,:)
	integer(int32) n,m,i,j
	
	n=size(A,1)
	m=size(A,2)
	if(.not. allocated(A_T) )allocate(A_T(m,n))
	
	do i=1,n
	  	do j=1, m
		  	A_T(j,i)=A(i,j)
	  	enddo
	enddo
	
 end function trans2
!================================================================================== 
subroutine inverse_rank_2(A,A_inv)
	real(real64),intent(in)::A(:,:)
	real(real64),allocatable::A_inv(:,:)
	real(real64) detA,detA_1
	integer(int32) m,n
	
	m=size(A,1)
	n=size(A,2)
	if(.not. allocated(A_inv) )allocate(A_inv(m,n))
	detA=det_mat(A,n)
	if(detA==0.0d0) stop "ERROR: inverse, detA=0"
	detA_1=1.0d0/detA
	if(n==2)then
	  	A_inv(1,1)=detA_1*A(2,2)
	  	A_inv(1,2)=-detA_1*A(1,2)
	  	A_inv(2,1)=-detA_1*A(2,1)
	  	A_inv(2,2)=detA_1*A(1,1)
	elseif(n==3)then
	  	A_inv(1,1)=detA_1*(A(2,2)*A(3,3)-A(2,3)*A(3,2))
	  	A_inv(1,2)=detA_1*(A(1,3)*A(3,2)-A(1,2)*A(3,3))
	  	A_inv(1,3)=detA_1*(A(1,2)*A(2,3)-A(1,3)*A(2,2))
	  	A_inv(2,1)=detA_1*(A(2,3)*A(3,1)-A(2,1)*A(3,3))
	  	A_inv(2,2)=detA_1*(A(1,1)*A(3,3)-A(1,3)*A(3,1))
	  	A_inv(2,3)=detA_1*(A(1,3)*A(2,1)-A(1,1)*A(2,3))
	  	A_inv(3,1)=detA_1*(A(2,1)*A(3,2)-A(2,2)*A(3,1))
	  	A_inv(3,2)=detA_1*(A(1,2)*A(3,1)-A(1,1)*A(3,2))
	  	A_inv(3,3)=detA_1*(A(1,1)*A(2,2)-A(1,2)*A(2,1))
	else
	  	print *, "ERROR: Aij with i=j=",n,"/=2or3"
	endif
	
 end subroutine inverse_rank_2
!================================================================================== 
!================================================================================== 
function inverse(A) result(A_inv)
	real(real64),intent(in)::A(:,:)
	real(real64),allocatable::A_inv(:,:)
	real(real64) detA,detA_1
	integer(int32) m,n
	
	m=size(A,1)
	n=size(A,2)
	if(.not. allocated(A_inv) )allocate(A_inv(m,n))
	detA=det_mat(A,n)
	if(detA==0.0d0) stop "ERROR: inverse, detA=0"
	detA_1=1.0d0/detA
	if(n==2)then
	  	A_inv(1,1)=detA_1*A(2,2)
	  	A_inv(1,2)=-detA_1*A(1,2)
	  	A_inv(2,1)=-detA_1*A(2,1)
	  	A_inv(2,2)=detA_1*A(1,1)
	elseif(n==3)then
	  	A_inv(1,1)=detA_1*(A(2,2)*A(3,3)-A(2,3)*A(3,2))
	  	A_inv(1,2)=detA_1*(A(1,3)*A(3,2)-A(1,2)*A(3,3))
	  	A_inv(1,3)=detA_1*(A(1,2)*A(2,3)-A(1,3)*A(2,2))
	  	A_inv(2,1)=detA_1*(A(2,3)*A(3,1)-A(2,1)*A(3,3))
	  	A_inv(2,2)=detA_1*(A(1,1)*A(3,3)-A(1,3)*A(3,1))
	  	A_inv(2,3)=detA_1*(A(1,3)*A(2,1)-A(1,1)*A(2,3))
	  	A_inv(3,1)=detA_1*(A(2,1)*A(3,2)-A(2,2)*A(3,1))
	  	A_inv(3,2)=detA_1*(A(1,2)*A(3,1)-A(1,1)*A(3,2))
	  	A_inv(3,3)=detA_1*(A(1,1)*A(2,2)-A(1,2)*A(2,1))
	else
	  	print *, "ERROR: Aij with i=j=",n,"/=2or3"
	endif
	
 end function inverse
!================================================================================== 
subroutine tensor_exponential(A,expA,TOL,itr_tol)
  	real(real64),intent(in)::A(:,:),TOL
  	real(real64),allocatable,intent(inout)::expA(:,:)
  	integer(int32), intent(in)::itr_tol
  	real(real64),allocatable::increA(:,:)
  	real(real64) increment,NN
  	integer(int32) i,j,n
	
  	if(.not. allocated(expA) )allocate(expA(size(A,1),size(A,2) ))
  	allocate(increA(size(A,1),size(A,2) ))
  	if(size(A,1)/=size(A,2)) stop "ERROR:tensor exp is not a square matrix"
	
  	expA(:,:)=0.0d0
  	do n=1,size(expA,1)
	  	expA(n,n)=1.0d0
  	enddo
  	NN=1.0d0
  	increA(:,:)=expA(:,:)
  	do n=1,itr_tol
	  	if(n>1)then
		  	NN       = NN*(NN+1.0d0)
	  	endif
	  	increA(:,:)=matmul(increA,A)
	  	expA(:,:)= expA(:,:)+1.0d0/NN*increA(:,:)
	  
	  	increment=0.0d0
	  	do i=1,size(A,1)
		  	do j=1,size(A,2)
			  	increment=increment+1.0d0/NN*increA(i,j)*increA(i,j)
		  	enddo
	  	enddo
	  
	  	if(increment<=TOL)then
		  	exit
	  	else
		  	if(n>=itr_tol)then
			   	stop "tensor exponential is not converged"
		  	endif
			cycle
	  	endif
  	enddo
  
  	deallocate(increA)
  
end subroutine tensor_exponential
!================================================================================== 
function identity_matrix(n) result(mat)
	integer(int32),intent(in) :: n ! rank
	real(real64) :: mat(n,n)
	integer(int32) :: i
	mat(:,:)=0.0d0
	do i=1,n
		mat(i,i)=1.0d0
	enddo

end function
!================================================================================== 

!================================================================================== 
function zero_matrix(n) result(mat)
	integer(int32),intent(in) :: n ! rank
	real(real64) :: mat(n,n)
	mat(:,:)=0.0d0

end function
!================================================================================== 
subroutine tensor_expo_der(A,expA_A,TOL,itr_tol)
  	real(real64),intent(in)::A(:,:),TOL
  	real(real64),allocatable,intent(inout)::expA_A(:,:,:,:)
  	integer(int32), intent(in)::itr_tol
  	real(real64),allocatable::increA_1(:,:),increA_2(:,:),increA_3(:,:,:,:),I_ij(:,:),A_inv(:,:)
  	real(real64) increment,NN
  	integer(int32) i,j,k,l,n,m,o
	
  	if(.not. allocated(expA_A) )allocate(expA_A(size(A,1),size(A,1),size(A,1),size(A,1) ))
  	allocate(I_ij(size(A,1),size(A,1) ))
  	allocate(increA_1(size(A,1),size(A,1) ))
  	allocate(increA_2(size(A,1),size(A,1) ))
  	allocate(increA_3(size(A,1),size(A,1),size(A,1),size(A,1) ) )
  	if(size(A,1)/=size(A,2)) stop "ERROR:tensor exp is not a square matrix"
  
  	call inverse_rank_2(A,A_inv)

  	I_ij(:,:)=0.0d0
  	do n=1,size(expA_A,1)
		I_ij(n,n)=1.0d0
  	enddo
  	NN=1.0d0
  
  	do i=1,size(A,1)
	  	do j=1,size(A,1)
		  	do k=1, size(A,1)
			  	do l=1, size(A,1)
				  	expA_A(i,j,k,l)=I_ij(i,k)*I_ij(l,j)
			  	enddo
		  	enddo
	  	enddo
  	enddo
  
  	increA_1(:,:)=I_ij(:,:)
  	increA_2(:,:)=I_ij(:,:)
  	do n=1,itr_tol
		if(n>2)then
			NN = NN*(NN+1.0d0)
		endif
		increA_1(:,:)=A_inv(:,:)
		increA_2(:,:)=matmul(increA_2,A)
	  
	  	increA_3(:,:,:,:)=0.0d0
	  	do m=1,n
			increA_1(:,:)=matmul(increA_1,A    )
		  
		  	increA_2(:,:)=matmul(increA_2,A_inv)

		  	do i=1,size(A,1)
				do j=1,size(A,1)
				  	do k=1, size(A,1)
					  	do l=1, size(A,1)
						  	increA_3(i,j,k,l)=increA_3(i,j,k,l)+increA_1(i,k)*increA_2(l,j)
						  	expA_A(i,j,k,l)=expA_A(i,j,k,l)+1.0d0/NN*increA_3(i,j,k,l)
					  	enddo
					enddo
			  	enddo
		  	enddo			
	  	enddo

	  	do i=1,size(A,1)
		  	do j=1,size(A,1)
			  	do k=1, size(A,1)
				  	do l=1, size(A,1)
					  	increment=increment+1.0d0/NN*increA_3(i,j,k,l)&
						  	*increA_3(i,j,k,l)&
						  	*increA_3(i,j,k,l)&
						  	*increA_3(i,j,k,l)
				  	enddo
			  	enddo
		  	enddo
	  	enddo			

	  	if(increment<=TOL)then
			exit
	  	else
		  	if(n>=itr_tol)then
			   	stop "tensor exponential is not converged"
		  	endif
		  	cycle
	  	endif
  	enddo
  
  	deallocate(increA_1,increA_2,increA_3,I_ij,A_inv)
  
end subroutine tensor_expo_der
!================================================================================== 

function GetNormRe(a) result(b)
	real(real64),intent(in)::a(:)
	real(real64) :: b
	b=dot_product(a,a)
end function
!================================================================================== 

function GetNormMatRe(a) result(b)
	real(real64),intent(in)::a(:,:)
	real(real64) :: b
	integer(int32) :: i,j
	b=0
	do i=1,size(a,1)
		do j=1,size(a,2)
			b=b+a(i,j)*a(i,j)
		enddo
	enddo
end function
!================================================================================== 

function trace(a) result(b)
	real(real64),intent(in)::a(:,:)
	real(real64) :: b
	integer(int32) :: i,j
	b=0
	do i=1,size(a,1)
		b=b+a(i,i)
	enddo
end function

!================================================================================== 
function sym(a,n) result(ret)
	real(real64),intent(in) :: a(:,:)
	real(real64) :: ret(n,n)
	integer(int32) :: i,n

	ret = 0.50d0*(a) + 0.50d0*transpose(a)

end function
!================================================================================== 

!================================================================================== 
function asym(a,n) result(ret)
	real(real64),intent(in) :: a(:,:)
	real(real64) :: ret(n,n)
	integer(int32) :: i,n

	ret = 0.50d0*(a) - 0.50d0*transpose(a)

end function
!================================================================================== 

function pi_value(n) result(res)
	integer(int32),intent(in)::n
	real(real64) :: ptr
	real(real64) :: an,bn,tn,pn
	real(real64) :: atr,btr,ttr
	real(real64) :: res

	integer(int32) :: i

	an=1.0d0
	bn=1.0d0/sqrt(2.0d0)
	tn=0.250d0
	pn=1.00d0
	do i=1,n
		atr=0.50d0*(an+bn)
		btr=dsqrt(an*bn)
		ttr=tn-pn*(atr-an)*(atr-an)
		ptr=2.0d0*pn

		an=atr
		bn=btr
		tn=ttr
		pn=ptr

		res=(atr+btr)*(atr+btr)/4.0d0/ttr
	enddo

end function
!================================================================================== 




!================================================================================== 
function fstring_int(x) result(a)
	integer(int32),intent(in) :: x
	character(len=20):: b
	character(len=:),allocatable	:: a

	write(b,*) x
	a = trim(adjustl(b))

end function
!================================================================================== 

!================================================================================== 
function fstring_logical(x) result(a)
	logical,intent(in) :: x
	character(len=5)	:: a

	write(a,*) x

end function
!================================================================================== 



!================================================================================== 
function fstring_String(x) result(a)
	type(String_),intent(in) :: x
	character(len=:),allocatable :: a

	a = trim(x%all)
end function
!================================================================================== 



!================================================================================== 
function fstring_int_len(x,length) result(a)
	integer(int32),intent(in) :: x
	integer(int32),intent(in) :: length
	character(len=length)	:: a

	if(x/=x  .or. abs(x) >= HUGE(int32) )then
		a=""
		return
	endif

	write(a,*) x
	a = adjustl(a)
end function
!================================================================================== 



!================================================================================== 
function fstring_real(x) result(a)
	real(real64),intent(in) :: x
	character(len=20):: b
	character(len=:),allocatable	:: a

	if(x/=x .or. abs(x) >= HUGE(real64) )then
		a=""
		return
	endif

	write(b,'(f0.8)') x
	a = trim(adjustl(b))



end function
!================================================================================== 

!================================================================================== 
function fstring_real32(x) result(a)
	real(real32),intent(in) :: x
	character(len=20):: b
	character(len=:),allocatable	:: a

	if(x/=x .or. abs(x) >= HUGE(real64) )then
		a=""
		return
	endif

	write(b,'(f0.8)') x
	a = trim(adjustl(b))



end function
!================================================================================== 

!================================================================================== 
function fstring_complex(x) result(a)
	complex(kind(0d0) ),intent(in) :: x
	character(len=30):: b
	character(len=:),allocatable	:: a

	if(x/=x  .or. abs(x) >= HUGE(real64) )then
		a=""
		return
	endif

	write(b,fmt = '(F0.0,SP,F0.0,"i")') x
	a = trim(adjustl(b))
end function
!================================================================================== 


!================================================================================== 
function fstring_real_len(x,length) result(a)
	real(real64),intent(in) :: x
	integer(int32),intent(in) :: length
	character(len=60)	:: a
	character*40						:: form

	if(x/=x .or. abs(x) >= HUGE(real64))then
		a=""
		return
	endif
	
	write(a,'(f0.10)') x
	a = adjustl(a)
end function
!================================================================================== 



!================================================================================== 
function fint(ch)	result(a)
	character(*),intent(in)			:: ch
	integer(int32)				:: a

	read(ch,*,err=1000) a
	return
1000 a = 0

end function
!================================================================================== 

!================================================================================== 
function fint16(ch)	result(a)
	character(*),intent(in)			:: ch
	integer(int16)				:: a

		read(ch,*,err=1001) a
	return
1001 a = 0

end function
!================================================================================== 



!================================================================================== 
function fint32(ch)	result(a)
	character(*),intent(in)			:: ch
	integer(int32)				:: a

		read(ch,*,err=1002) a
	return
1002 a = 0

end function
!================================================================================== 


!================================================================================== 
function fint64(ch)	result(a)
	character(*),intent(in)			:: ch
	integer(int64)				:: a

		read(ch,*,err=1003) a
	return
1003 a = 0

end function
!================================================================================== 




!================================================================================== 
function freal(ch)	result(a)
	character(*),intent(in)			:: ch
	real(real64)				:: a

		read(ch,*,err=1004) a
	return
1004 a = 0.0d0

end function
!================================================================================== 


!================================================================================== 
function freal32(ch)	result(a)
	character(*),intent(in)			:: ch
	real(real32)				:: a

		read(ch,*,err=1005) a
	return
1005 a = 0

end function
!================================================================================== 


!================================================================================== 
function freal64(ch)	result(a)
	character(*),intent(in)			:: ch
	real(real64)				:: a

		read(ch,*,err=1006) a
	return
1006 a = 0

end function
!================================================================================== 


!================================================================================== 
function freal128(ch)	result(a)
	character(*),intent(in)			:: ch
	real(real64)				:: a

		read(ch,*,err=1007) a
	return
1007 a = 0

end function
!================================================================================== 





!================================================================================== 
function input_Int(default,option) result(val)
	integer(int32),intent(in) :: default
	integer(int32),optional,intent(in)::option
	integer(int32) :: val

	if(present(option) )then
		val=option
	else
		val=default
	endif

end function
!================================================================================== 




!================================================================================== 
function input_Real(default,option) result(val)
	real(real64),intent(in) :: default
	real(real64),optional,intent(in)::option
	real(real64) :: val

	if(present(option) )then
		val=option
	else
		val=default
	endif

end function
!================================================================================== 



!================================================================================== 
function input_Real32(default,option) result(val)
	real(real32),intent(in) :: default
	real(real32),optional,intent(in)::option
	real(real32) :: val

	if(present(option) )then
		val=option
	else
		val=default
	endif

end function
!================================================================================== 


!================================================================================== 
function input_Complex(default,option) result(val)
	complex(real64),intent(in) :: default
	complex(real64),optional,intent(in)::option
	complex(real64) :: val

	if(present(option) )then
		val=option
	else
		val=default
	endif

end function
!================================================================================== 




!================================================================================== 
function input_IntVec(default,option) result(val)
	integer(int32),intent(in) :: default(:)
	integer(int32),optional,intent(in)::option(:)
	integer(int32),allocatable :: val(:)
	integer(int32) :: n,m

	if(present(option) )then
		n=size(option,1)
		allocate(val(n) )
		val(:)=option(:)
	else
		n=size(default,1)
		allocate(val(n) )
		val(:)=default(:)
	endif

end function
!================================================================================== 

!================================================================================== 
function input_Realvec(default,option) result(val)
	real(real64),intent(in) :: default(:)
	real(real64),optional,intent(in)::option(:)
	real(real64),allocatable :: val(:)
	integer(int32) :: n,m

	if(present(option) )then
		n=size(option,1)
		allocate(val(n) )
		val(:)=option(:)
	else
		n=size(default,1)
		allocate(val(n) )
		val(:)=default(:)
	endif

end function
!================================================================================== 




!================================================================================== 
function input_IntArray(default,option) result(val)
	integer(int32),intent(in) :: default(:,:)
	integer(int32),optional,intent(in)::option(:,:)
	integer(int32),allocatable :: val(:,:)
	integer(int32) :: n,m

	if(present(option) )then
		n=size(option,1)
		m=size(option,2)
		allocate(val(n,m) )
		val(:,:)=option(:,:)
	else
		n=size(default,1)
		m=size(default,2)
		allocate(val(n,m) )
		val(:,:)=default(:,:)
	endif

end function
!================================================================================== 

!================================================================================== 
function input_RealArray(default,option) result(val)
	real(real64),intent(in) :: default(:,:)
	real(real64),optional,intent(in)::option(:,:)
	real(real64),allocatable :: val(:,:)
	integer(int32) :: n,m

	if(present(option) )then
		n=size(option,1)
		m=size(option,2)
		allocate(val(n,m) )
		val(:,:)=option(:,:)
	else
		n=size(default,1)
		m=size(default,2)
		allocate(val(n,m) )
		val(:,:)=default(:,:)
	endif

end function
!================================================================================== 


!================================================================================== 
function input_String(default,option) result(val)
	character(*),intent(in) :: default
	character(*),optional,intent(in)::option
	character(200 ) :: val

	if(present(option) )then
		val=option
	else
		val=default
	endif

end function
!================================================================================== 

!================================================================================== 
function input_logical(default,option) result(val)
	logical,intent(in) :: default
	logical,optional,intent(in)::option
	logical :: val

	if(present(option) )then
		val=option
	else
		val=default
	endif

end function
!================================================================================== 

function zeroif_Int(val,negative,positive) result(retval)
	integer(int32),intent(in)::val
	integer(int32) :: retval
	logical,optional,intent(in) :: negative,positive

	if(val/=val)then
		print *, "ERROR :: MAthClass >> zeroif_Int is invalid"
	endif
	retval=val
	if(present(negative) )then
		if(negative .eqv. .true.)then
			if(val<0)then
				retval=0
			endif
		endif
	endif
	
	if(present(positive) )then
		if(positive .eqv. .true.)then
			if(val>0)then
				retval=0
			endif
		endif
	endif

end function
	

function zeroif_Real(val,negative,positive) result(retval)
	real(real64),intent(in)::val
	real(real64) :: retval
	logical,optional,intent(in) :: negative,positive

	if(val/=val)then
		print *, "ERROR :: MAthClass >> zeroif_Int is invalid"
	endif
	retval=val
	if(present(negative) )then
		if(negative .eqv. .true.)then
			if(val<0.0d0)then
				retval=0.0d0
			endif
		endif
	endif
	
	if(present(positive) )then
		if(positive .eqv. .true.)then
			if(val>0.0d0)then
				retval=0.0d0
			endif
		endif
	endif

end function

! ########################################################
subroutine removeWord_String(str,keyword,itr,Compare)
	character(*),intent(inout)::str
	character(*),intent(in   )::keyword
	
	integer(int32) :: len_total,len_kw,i,j,n,itr_max
	integer(int32),optional,intent(in)::itr
	logical,optional,intent(in)::Compare
	logical :: bk
	

	if(present(Compare))then
		if(Compare .eqv. .true.)then
			print *, "Before :: ",str	
		endif
	endif

	itr_max=input(default=1,option=itr)
	bk=.false.
	len_total=len(str)
	len_kw	 =len(keyword)

	do i=1,itr_max
		n=index(str,keyword)
		do j=n,n+len_kw
			str(j:j)=" "
		enddo
		if(n==0)then
			exit
		endif	
	enddo

	if(present(Compare))then
		if(Compare .eqv. .true.)then
			print *, "After :: ",str	
		endif
	endif


	
end subroutine
! ########################################################


! ########################################################
function Invariant_I1(sigma) result(I1)
	real(real64),intent(in) :: sigma(:,:)
	real(real64) :: I1
	integer(int32) :: i,j

	I1=0.0d0
	do i=1,size(sigma,1)
		I1=I1+sigma(i,i)
	enddo

end function
! ########################################################


! ########################################################
function Invariant_J2(sigma) result(J2)
	real(real64),intent(in) :: sigma(:,:)
	real(real64) :: I1,J2,delta(3,3),M_d(3,3)
	integer(int32) :: i,j

	delta(:,:)=0.0d0
	delta(1,1)=1.0d0
	delta(2,2)=1.0d0
	delta(3,3)=1.0d0
	
	I1=Invariant_I1(sigma)
	M_d(:,:)=sigma(:,:)-I1/3.0d0*delta(:,:)
	J2=0.0d0
	do i=1,size(sigma,1)
		do j=1,size(sigma,1)
			J2=J2+0.50d0*M_d(i,j)*M_d(i,j)
		enddo
	enddo

end function
! ########################################################


! ########################################################
function Invariant_J3(sigma) result(J3)
	real(real64),intent(in) :: sigma(:,:)
	real(real64) :: I1,J3,delta(3,3),M_d(3,3)
	integer(int32) :: i,j,k

	delta(:,:)=0.0d0
	delta(1,1)=1.0d0
	delta(2,2)=1.0d0
	delta(3,3)=1.0d0
	
	I1=Invariant_I1(sigma)
	M_d(:,:)=sigma(:,:)-I1/3.0d0*delta(:,:)
	J3=0.0d0
	
	do i=1,size(sigma,1)
		do j=1,size(sigma,1)
			do k=1,size(sigma,1)
				J3=J3+1.0d0/3.0d0*M_d(i,j)*M_d(j,k)*M_d(k,i)
			enddo
		enddo
	enddo

end function
! ########################################################

! ########################################################
function Invariant_theta(sigma) result(theta)
	real(real64),intent(in) :: sigma(:,:)
	real(real64) :: I1,J2,J3,delta(3,3),M_d(3,3),theta
	integer(int32) :: i,j,k

	delta(:,:)=0.0d0
	delta(1,1)=1.0d0
	delta(2,2)=1.0d0
	delta(3,3)=1.0d0
	J2=Invariant_J2(sigma)
	J3=Invariant_J3(sigma)
	theta=1.0d0/3.0d0*asin(-3.0d0*sqrt(3.0d0)*0.50d0*J3/J2/sqrt(J2)  )

end function
! ########################################################

! ########################################################
function inv_mod(a_in,m_in,ItrMax) result(x)
	integer(int32),intent(in) :: a_in,m_in
	integer(int32),optional,intent(in) :: ItrMax
	integer(int32) :: d, q,t, Kmat_n(2,2),Kmat_npp(2,2),k,itr_tol,r0,r1,r2,i,x,y,m0
	integer(int32) :: a,m

	a=a_in
	m=m_in
	
	itr_tol=input(default=10000,option=ItrMax)
	! inverse modula by Extended Euclidean algorithm
	! d = e^-1 (mod (lambda))
	! d*e = 1 (mod (lambda))
	! one integer q
	! d*e - q*lambda = 1, e, lambda are known, d, q are unknown.
	! get d, q by extended Euclidean algorithm
	! gcd(e, lambda) = 1
	!Kmat_npp(1,1)=1
	!Kmat_npp(1,2)=0
	!Kmat_npp(2,1)=0
	!Kmat_npp(2,2)=1
	!r0=e
	!r1=lambda
	!do i=1, itr_tol
	!	r2=mod(r0,r1)
	!	if(r2==0)then
	!		print *, "gcd of ",e," and",lambda,"is", r1
	!		exit
	!	endif
	!	k=(r0-r2)/r1
	!	Kmat_n(1,1)=0
	!	Kmat_n(1,2)=1
	!	Kmat_n(2,1)=1
	!	Kmat_n(2,2)=-k
	!	a=matmul(Kmat_npp,Kmat_n)
	!	Kmat_npp=a
	!	print *, r0,"=",k,"*",r1,"+",r2
	!	r0=r1
	!	r1=r2
	!enddo
	!d = Kmat_npp(1,2)
	!print *, "Kmat_npp=",Kmat_npp
	! cited by https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
	m0=m
	y=0
	x=1
	if(gcd(a,m)/=1 )then
		a = mod(a,m) 
		do x=1,m
			if( mod(a*x,m)==1)then
				return
			endif
		enddo
	endif
	if(m==1)then
		return
	endif
	
	do i=1,itr_tol
		if(a > 1)then
			q=(a -mod(a,m))/m
			
			t=m

			m= mod(a,m)
			a=t
			t=y

			y=x - q*y
			x=t
		else
			exit
		endif
	enddo
	if(x < 0)then
		x = x+m0
	endif

end function
! ########################################################

! ########################################################
function gcd(a,b,ItrMax) result(c)
	integer(int32),intent(in) :: a,b
	integer(int32),optional,intent(in) :: ItrMax
	integer(int32) :: i,r0,r1,r2,k,itr_tol,c
	c=1
	itr_tol=input(default=10000,option=ItrMax)
	r0=a
	r1=b
	do i=1, itr_tol
		r2=mod(r0,r1)	
		if(r2==0)then
			!print *, "gcd of ",a," and",b,"is", r1
			exit
		endif
		k=(r0-r2)/r1
		!print *, r0,"=",k,"*",r1,"+",r2
		r0=r1
		r1=r2
	enddo
	c=r1

end function
! ########################################################


! ########################################################
function lcm(a,b,ItrMax) result(c)
	integer(int32),intent(in) :: a,b
	integer(int32),optional,intent(in) :: ItrMax
	integer(int32) :: i,r0,r1,r2,k,itr_tol,c

	itr_tol=input(default=10000,option=ItrMax)
	r0=a
	r1=b
	do i=1, itr_tol
		r2=mod(r0,r1)
		if(r2==0)then
			!print *, "gcd of ",a," and",b,"is", r1
			exit
		endif
		k=(r0-r2)/r1
		!print *, r0,"=",k,"*",r1,"+",r2
		r0=r1
		r1=r2
	enddo
	c=a*b/r1


end function
! ########################################################


! ########################################################
function convertStringToInteger(message) result(ret)
	character(*),intent(in):: message
	character(1) :: x
	character(2*len(message) ) :: ret
	integer(int32) :: i
	ret = ""
	!allocate(ret(len(message)*2 ) )
	do i=1,len(message)
		x =  message(i:i)
		select case(x)
			case(" ")
				cycle
			case("a","A")
				ret(2*i-1:2*i) =  "01"
			case("b","B")
				ret(2*i-1:2*i) =  "02"
			case("c","C")
				ret(2*i-1:2*i) =  "03"
			case("d","D")
				ret(2*i-1:2*i) =  "04"
			case("e","E")
				ret(2*i-1:2*i) =  "05"
			case("f","F")
				ret(2*i-1:2*i) =  "06"
			case("g","G")
				ret(2*i-1:2*i) =  "07"
			case("h","H")
				ret(2*i-1:2*i) =  "08"
			case("i","I")
				ret(2*i-1:2*i) =  "09"
			case("j","J")
				ret(2*i-1:2*i) =  "10"
			case("k","K")
				ret(2*i-1:2*i) =  "11"
			case("l","L")
				ret(2*i-1:2*i) =  "12"
			case("m","M")
				ret(2*i-1:2*i) =  "13"
			case("n","N")
				ret(2*i-1:2*i) =  "14"
			case("o","O")
				ret(2*i-1:2*i) =  "15"
			case("p","P")
				ret(2*i-1:2*i) =  "16"
			case("q","Q")
				ret(2*i-1:2*i) =  "17"
			case("r","R")
				ret(2*i-1:2*i) =  "18"
			case("s","S")
				ret(2*i-1:2*i) =  "19"
			case("t","T")
				ret(2*i-1:2*i) =  "20"
			case("u","U")
				ret(2*i-1:2*i) =  "21"
			case("v","V")
				ret(2*i-1:2*i) =  "22"
			case("w","W")
				ret(2*i-1:2*i) =  "23"
			case("x","X")
				ret(2*i-1:2*i) =  "24"
			case("y","Y")
				ret(2*i-1:2*i) =  "25"
			case("z","Z")
				ret(2*i-1:2*i) =  "26"
		end select
	enddo

end function
! ########################################################


! ########################################################
function convertIntegerToString(message) result(ret)
	character(*),intent(in):: message
	character(2) :: x
	character(len(message) ) :: ret
	integer(int32) :: i
	ret = ""
	!allocate(ret(len(message)*2 ) )
	do i=1,len(message)
		x(1:2) =  message(2*i-1:2*i)
		select case(x)
			case("99")
				cycle
			case(" ")
				cycle
			case("01")
				ret(i:i) =  "a"
			case("02")
				ret(i:i) =  "b"
			case("03")
				ret(i:i) =  "c"
			case("04")
				ret(i:i) =  "d"
			case("05")
				ret(i:i) =  "e"
			case("06")
				ret(i:i) =  "f"
			case("07")
				ret(i:i) =  "g"
			case("08")
				ret(i:i) =  "h"
			case("09")
				ret(i:i) =  "i"
			case("10")
				ret(i:i) =  "j"
			case("11")
				ret(i:i) =  "k"
			case("12")
				ret(i:i) =  "l"
			case("13")
				ret(i:i) =  "m"
			case("14")
				ret(i:i) =  "n"
			case("15")
				ret(i:i) =  "o"
			case("16")
				ret(i:i) =  "p"
			case("17")
				ret(i:i) =  "q"
			case("18")
				ret(i:i) =  "r"
			case("19")
				ret(i:i) =  "s"
			case("20")
				ret(i:i) =  "t"
			case("21")
				ret(i:i) =  "u"
			case("22")
				ret(i:i) =  "v"
			case("23")
				ret(i:i) =  "w"
			case("24")
				ret(i:i) =  "x"
			case("25")
				ret(i:i) =  "y"
			case("26")
				ret(i:i) =  "z"
		end select
	enddo

end function
! ########################################################
! ########################################################
subroutine rsa_keygen(prime1,prime2,seed,id_rsa,id_rsa_pub)
	integer(int32),intent(in) :: prime1,prime2,seed
	integer(int32),intent(out) :: id_rsa(2),id_rsa_pub(2)
	integer(int32) :: n,e,lambda,d,p,q
	
	p=prime1
	q=prime2

	n=p*q
	lambda=(p-1)*(q-1)/gcd(p-1,q-1)
	!print *, "lambda=",lambda
	
	id_rsa_pub(1)=n
	id_rsa_pub(2)=seed

	id_rsa(1)=n
	id_rsa(2)=inv_mod(seed, lambda) !get d
	
	print *, "#######################################################"
	print *, "Encrypted by RSA algorithm, public keys "
	print *, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
	print *, "Multiplication of two prime numbers is ",id_rsa_pub(1)
	print *, "Seed value (1 < seed < ",id_rsa_pub(1),") is", id_rsa_pub(2)
	print *, "Notice:: message should be (1 < seed < ",id_rsa_pub(1),")."
	print *, "#######################################################"


end subroutine
! ########################################################

! ########################################################
function rsa_encrypt(id_rsa_pub,message) result(ciphertext)
	integer(int32),intent(in) ::id_rsa_pub(2),message
	integer(int32) :: ciphertext,i

	ciphertext = 1
	do i=1, id_rsa_pub(2)
		ciphertext= mod(ciphertext* message,  id_rsa_pub(1) )
	enddo

end function
! ########################################################

! ########################################################
function rsa_decrypt(id_rsa,ciphertext) result(message)
	integer(int32),intent(in) ::id_rsa(2),ciphertext
	integer(int32) :: d,n,e,message,i

	
	message = 1
	do i=1, id_rsa(2)
		message= mod(message* ciphertext,  id_rsa(1) )
	enddo

end function
! ########################################################

function IsItNumber(char) result(res)
	character(*),intent(inout) :: char
	logical :: res
	integer :: i
	character(1) :: firstchar

	res=.false.
	! search all
	firstchar=trim(adjustl(char(1:1)))

	if(firstchar == "1" )then
		res=.true.
		return
	elseif(firstchar == "2" )then
		res=.true.
		return
	elseif(firstchar == "3" )then
		res=.true.
		return
	elseif(firstchar == "4" )then
		res=.true.
		return
	elseif(firstchar == "5" )then
		res=.true.
		return
	elseif(firstchar == "6" )then
		res=.true.
		return
	elseif(firstchar == "7" )then
		res=.true.
		return
	elseif(firstchar == "8" )then
		res=.true.
		return
	elseif(firstchar == "9" )then
		res=.true.
		return						
	elseif(firstchar == "0" )then
		res=.true.
		return						
	elseif(firstchar == "." )then
		res=.true.
		return							
	else
		return
	endif


end function IsItNumber


! BitInversion
!recursive function BitInversion(i,numBit) result(ret)
!	integer(int32),intent(in) :: i
!	integer(int32),intent(in) :: numBit
!
!	if(numBit==1)then
!		! 1 Bit 0 or 1
!		
!	elseif(numBit==2)then
!	elseif(numBit==3)then
!	if(numBit > 3) then
!	endif
!	
!end function

! Window functions

function RectangularWindow(Width,DataSize) result(ret)
	integer(int32),intent(in) :: Width,DataSize
	real(real64) :: ret(DataSize)

	ret = 0.0d0
	ret(DataSize/2-Width/2:DataSize/2+Width/2) = 1

end function

function HanningWindow(Width,DataSize) result(ret)
	integer(int32),intent(in) :: Width,DataSize
	real(real64) :: ret(DataSize)
	type(Math_) :: math
	integer(int32) :: i
	
	print *, "[CAUTION] EXPERIMENTAL!"
	
	ret = 0.0d0
	do i=1,width/2
		ret(DataSize/2-i) &
		= 0.50d0 - 0.50d0*cos(2.0d0*Math%PI*i/(Width/2) )
		ret(DataSize/2+i) &
		= 0.50d0 - 0.50d0*cos(2.0d0*Math%PI*i/(Width/2) )
	enddo

end function


function HammingWindow(Width,DataSize) result(ret)
	integer(int32),intent(in) :: Width,DataSize
	real(real64) :: ret(DataSize)
	type(Math_) :: math
	integer(int32) :: i

	print *, "[CAUTION] EXPERIMENTAL!"
	

	ret = 0.0d0
	do i=1,width/2
		ret(DataSize/2-i) &
		= 0.540d0 - 0.46d0*cos(2.0d0*Math%PI*i/(Width/2) )
		ret(DataSize/2+i) &
		= 0.540d0 - 0.46d0*cos(2.0d0*Math%PI*i/(Width/2) )
	enddo

end function
! #######################################################################
function log2(x) result(ret)
	real(real64),intent(in) :: x
	real(real64) :: ret

	ret = log(x)/log(2.0d0)

end function
! #######################################################################


! #######################################################################
pure function day(unit) result(ret)
	character(*),intent(in):: unit
	real(real64) :: ret
	
	if(unit(1:1)=="S" .or. unit(1:1)=="s")then
		! day to second
		ret = 24.0d0*60.0d0*60.0d0
		return
	endif
	
	if(unit(1:1)=="M" .or. unit(1:1)=="m")then
		! day to minutes
		ret = 24.0d0*60.0d0
		return
	endif
	
	if(unit(1:1)=="H" .or. unit(1:1)=="h")then
		! hour to minutes
		ret = 24.0d0
		return
	endif
	
	if(unit(1:1)=="D" .or. unit(1:1)=="d")then
		! day to minutes
		ret = 1.0d0
		return
	endif
	
	if(unit(1:1)=="Y" .or. unit(1:1)=="y")then
		! day to year
		ret = 1.0d0/365.0d0
		return
	endif

end function
! #######################################################################

! #######################################################################
pure recursive function factorialInt32(n) result(ret)
	integer(int32),intent(in) :: n
	integer(int64) :: i,ret			

	ret=1
	do i=1,n
		ret = ret*i
	enddo

end function
! #######################################################################

! #######################################################################
pure recursive function factorialReal64(n) result(ret)
	real(real64),intent(in) :: n
	real(real64) :: ret			
	integeR(int32) :: i

	ret=1.0d0
	do i=1,int(n)
		ret = ret*dble(i)
	enddo

end function
! #######################################################################

pure function comb(n,r) result(ret)
	integer(int32),intent(in) :: n,r
	real(real64) :: ret
	integer(int32) :: i
	real(real64),allocatable :: buf1(:),buf2(:),buf3(:)
	
	if(n-r<0)then
		ret = 0.0d0
		return
	endif

	if(n<=10)then
		ret = factorial(n)/(factorial(r)*factorial(n-r))
	else
		allocate(buf1(n),buf2(n),buf3(n))
		do concurrent (i=1:n)
			buf1(i) = i
		end do
		do concurrent (i=1:r)
			buf2(i) = i
		end do
		do concurrent (i=1:n-r)
			buf3(i) = i
		end do
		
		do concurrent (i=1:r)
			buf1(i) = buf1(i)/buf2(i)
		end do
		do concurrent (i=1:n-r)
			buf1(i) = buf1(i)/buf3(i)
		end do
		
		ret=1.0d0
		do i=1,n
			ret = ret * buf1(i)	
		enddo
		ret =dble(nint(ret))

		!by array
	endif

end function

function stringFromChar(charval) result(ret)
	character(*),intent(in):: charval
	type(String_) :: ret

	ret = charval

end function
! #######################################################################

function zfill(intval, n) result(ret)
	integer(int32),intent(in) :: intval,n
	character(n) :: ret
	character(:),allocatable :: fmt
	
	fmt = '(I'//str(n)//'.'//str(n)//')'
	write(ret(1:n),fmt) intval

end function


end module MathClass