2025-04-23 13:43:40 +08:00
/********************************************************
2024-09-10 15:45:07 +08:00
* █ █ █ █ █ █ ╗ █ █ █ █ █ █ ╗ █ █ █ █ █ █ █ █ ╗ █ █ ╗
* █ █ ╔ ═ ═ ═ ═ ╝ █ █ ╔ ═ ═ ═ ═ ╝ ╚ ═ ═ █ █ ╔ ═ ═ ╝ █ █ ║
* █ █ ║ █ █ █ ╗ █ █ ║ █ █ ║ █ █ ║
* █ █ ║ █ █ ║ █ █ ║ █ █ ║ █ █ ║
* ╚ █ █ █ █ █ █ ╔ ╝ ╚ █ █ █ █ █ █ ╗ █ █ ║ █ █ █ █ █ █ █ ╗
* ╚ ═ ═ ═ ═ ═ ╝ ╚ ═ ═ ═ ═ ═ ╝ ╚ ═ ╝ ╚ ═ ═ ═ ═ ═ ═ ╝
* Geophysical Computational Tools & Library ( GCTL )
*
* Copyright ( c ) 2023 Yi Zhang ( yizhang - geo @ zju . edu . cn )
*
* GCTL is distributed under a dual licensing scheme . You can redistribute
* it and / or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation , either version 2
* of the License , or ( at your option ) any later version . You should have
* received a copy of the GNU Lesser General Public License along with this
* program . If not , see < http : //www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v .2 . would prevent you from using
* the GCTL , please consider the option to obtain a commercial license for a
* fee . These licenses are offered by the GCTL ' s original author . As a rule ,
* licenses are provided " as-is " , unlimited in time for a one time fee . Please
* send corresponding requests to : yizhang - geo @ zju . edu . cn . Please do not forget
* to include some description of your company and the realm of its activities .
* Also add information on how to contact you by electronic and paper mail .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2025-04-23 13:43:40 +08:00
# include "gmath.h"
int gctl : : random ( int low , int hig )
{
return rand ( ) % ( hig - low + 1 ) + low ;
}
double gctl : : random ( double low , double hig )
{
double f = ( double ) rand ( ) / RAND_MAX ;
return f * ( hig - low ) + low ;
}
std : : complex < double > gctl : : random ( std : : complex < double > low , std : : complex < double > hig )
{
std : : complex < double > c ;
double r = ( double ) rand ( ) / RAND_MAX ;
double i = ( double ) rand ( ) / RAND_MAX ;
double rh = std : : max ( hig . real ( ) , low . real ( ) ) ;
double rl = std : : min ( hig . real ( ) , low . real ( ) ) ;
double ih = std : : max ( hig . imag ( ) , low . imag ( ) ) ;
double il = std : : min ( hig . imag ( ) , low . imag ( ) ) ;
c . real ( r * ( rh - rl ) + rl ) ;
c . imag ( i * ( ih - il ) + il ) ;
return c ;
}
bool gctl : : isequal ( double f , double v , double eps )
{
return fabs ( f - v ) < eps ;
}
double gctl : : sign ( double a )
{
if ( a > GCTL_ZERO ) return 1.0 ;
if ( a < - 1.0 * GCTL_ZERO ) return - 1.0 ;
return 0.0 ;
}
//利用二分法求一个正数的n次方根 注意输入值小于1的情况
double gctl : : sqrtn ( double d , int n , double eps )
{
double xmin , xmax , halfx ;
if ( d = = 1 )
{
return d ;
}
else if ( d > 1 )
{
xmin = 1 ;
xmax = d ;
halfx = 0.5 * ( xmin + xmax ) ;
while ( fabs ( d - pow ( halfx , n ) ) > eps )
{
if ( pow ( halfx , n ) > d )
{
xmax = halfx ;
halfx = 0.5 * ( xmin + xmax ) ;
}
else
{
xmin = halfx ;
halfx = 0.5 * ( xmin + xmax ) ;
}
}
}
else
{
xmin = 0 ;
xmax = 1 ;
halfx = 0.5 * ( xmin + xmax ) ;
while ( fabs ( d - pow ( halfx , n ) ) > eps )
{
if ( pow ( halfx , n ) > d )
{
xmax = halfx ;
halfx = 0.5 * ( xmin + xmax ) ;
}
else
{
xmin = halfx ;
halfx = 0.5 * ( xmin + xmax ) ;
}
}
}
return halfx ;
}
double gctl : : geographic_area ( double lon1 , double lon2 , double lat1 , double lat2 , double R )
{
return fabs ( R * R * ( arc ( lon2 ) - arc ( lon1 ) ) * ( sind ( lat2 ) - sind ( lat1 ) ) ) ;
}
double gctl : : geographic_distance ( double lon1 , double lon2 , double lat1 , double lat2 , double R )
{
double n1 = arc ( lon1 ) , n2 = arc ( lon2 ) , t1 = arc ( lat1 ) , t2 = arc ( lat2 ) ;
double a = sin ( 0.5 * ( t2 - t1 ) ) , b = sin ( 0.5 * ( n2 - n1 ) ) ;
return 2 * R * asin ( sqrt ( a * a + cos ( t1 ) * cos ( t2 ) * b * b ) ) ;
}
double gctl : : ellipse_radius_2d ( double x_len , double y_len , double arc , double x_arc )
{
if ( fabs ( x_len - y_len ) < 1e-16 ) // 就是个圆 直接加
{
return 0.5 * ( x_len + y_len ) ;
}
return sqrt ( power2 ( x_len * cos ( arc - x_arc ) ) + power2 ( y_len * sin ( arc - x_arc ) ) ) ;
}
void gctl : : ellipse_plus_elevation_2d ( double x_len , double y_len , double arc , double elev ,
double & out_arc , double & out_rad , double x_arc )
{
if ( fabs ( x_len - y_len ) < 1e-8 ) // 就是个圆 直接加
{
out_arc = arc ;
out_rad = 0.5 * ( x_len + y_len ) + elev ;
return ;
}
if ( fabs ( arc ) < 1e-8 ) // 弧度太小 直接加和
{
out_arc = arc ;
out_rad = x_len + elev ;
return ;
}
if ( fabs ( fabs ( arc ) - 0.5 * GCTL_Pi ) < 1e-8 ) // 到了弧顶 直接加和
{
out_arc = arc ;
out_rad = y_len + elev ;
return ;
}
double ellip_rad = ellipse_radius_2d ( x_len , y_len , arc , x_arc ) ;
double alpha = atan ( x_len * x_len * sin ( arc ) / ( y_len * y_len * cos ( arc ) ) ) ;
double sin_alpha = sin ( alpha ) ;
double lx = ellip_rad * sin ( alpha - arc ) / sin_alpha ;
double lr = ellip_rad * sin ( arc ) / sin_alpha + elev ;
out_rad = sqrt ( lx * lx + lr * lr - 2.0 * lx * lr * cos ( GCTL_Pi - alpha ) ) ;
out_arc = acos ( ( lx * lx + out_rad * out_rad - lr * lr ) / ( 2.0 * out_rad * lx ) ) ;
if ( arc < 0.0 ) out_arc * = - 1.0 ;
return ;
}
double gctl : : ellipsoid_radius ( double x_len , double y_len , double z_len , double phi , double theta )
{
return x_len * y_len * z_len / sqrt ( pow ( y_len * z_len * sin ( theta ) * cos ( phi ) , 2 ) +
pow ( x_len * z_len * sin ( theta ) * sin ( phi ) , 2 ) + pow ( x_len * y_len * cos ( theta ) , 2 ) ) ;
}
// 使用牛顿迭代法计算一个矩阵的近似逆
double gctl : : newton_inverse ( const _2d_matrix & in_mat , _2d_matrix & inverse_mat ,
double epsilon , int iter_times , bool initiate )
{
if ( in_mat . empty ( ) )
throw runtime_error ( " The input matrix is empty. Thrown by gctl::newton_inverse(...) " ) ;
if ( in_mat . row_size ( ) ! = in_mat . col_size ( ) )
throw logic_error ( " The input matrix is square. Thrown by gctl::newton_inverse(...) " ) ;
if ( iter_times < 0 )
throw invalid_argument ( " Invalid iteration times. Thrown by gctl::newton_inverse(...) " ) ;
int m_size = in_mat . row_size ( ) ;
if ( initiate )
{
// 初始化逆矩阵 使用输入矩阵的对角元素构建初始矩阵
if ( ! inverse_mat . empty ( ) ) inverse_mat . clear ( ) ;
inverse_mat . resize ( m_size , m_size , 0.0 ) ;
for ( int i = 0 ; i < m_size ; i + + )
{
inverse_mat [ i ] [ i ] = 1.0 / in_mat [ i ] [ i ] ;
}
}
if ( inverse_mat . row_size ( ) ! = m_size | | inverse_mat . col_size ( ) ! = m_size )
throw logic_error ( " Invalid output matrix size. From gctl::newton_inverse(...) " ) ;
// 迭代的收敛条件 || E - in_mat*inverse_mat ||_inf < 1
// 计算矩阵的无穷大范数
double maxi_mod = 0.0 , mod , ele ;
for ( int i = 0 ; i < m_size ; i + + )
{
mod = 0.0 ;
for ( int j = 0 ; j < m_size ; j + + )
{
ele = 0.0 ;
for ( int k = 0 ; k < m_size ; k + + )
{
ele + = in_mat [ i ] [ k ] * inverse_mat [ k ] [ j ] ;
}
if ( i = = j )
{
mod + = GCTL_FABS ( 1.0 - ele ) ;
}
else
{
mod + = GCTL_FABS ( ele ) ;
}
}
maxi_mod = GCTL_MAX ( maxi_mod , mod ) ;
}
if ( maxi_mod > = 1.0 )
{
GCTL_ShowWhatError ( " The iteration may not converge. From gctl::newton_inverse(...) " ,
GCTL_WARNING_ERROR , 0 , 0 , 0 ) ;
}
array < double > col_ax ( m_size , 0.0 ) ; // A*X 的列向量
_2d_matrix tmp_mat ( m_size , m_size , 0.0 ) ;
for ( int t = 0 ; t < iter_times ; t + + )
{
if ( maxi_mod < = epsilon )
break ;
for ( int i = 0 ; i < m_size ; i + + )
{
for ( int j = 0 ; j < m_size ; j + + )
{
tmp_mat [ i ] [ j ] = inverse_mat [ i ] [ j ] ;
}
}
for ( int n = 0 ; n < m_size ; n + + )
{
for ( int i = 0 ; i < m_size ; i + + )
{
for ( int j = 0 ; j < m_size ; j + + )
{
col_ax [ j ] = 0.0 ;
for ( int k = 0 ; k < m_size ; k + + )
{
col_ax [ j ] + = in_mat [ j ] [ k ] * tmp_mat [ k ] [ i ] ;
}
col_ax [ j ] * = - 1.0 ;
}
col_ax [ i ] + = 2.0 ;
ele = 0.0 ;
for ( int j = 0 ; j < m_size ; j + + )
{
ele + = tmp_mat [ n ] [ j ] * col_ax [ j ] ;
}
inverse_mat [ n ] [ i ] = ele ;
}
}
maxi_mod = 0.0 ;
for ( int i = 0 ; i < m_size ; i + + )
{
mod = 0.0 ;
for ( int j = 0 ; j < m_size ; j + + )
{
ele = 0.0 ;
for ( int k = 0 ; k < m_size ; k + + )
{
ele + = in_mat [ i ] [ k ] * inverse_mat [ k ] [ j ] ;
}
if ( i = = j )
{
mod + = GCTL_FABS ( 1.0 - ele ) ;
}
else
{
mod + = GCTL_FABS ( ele ) ;
}
}
maxi_mod = GCTL_MAX ( maxi_mod , mod ) ;
}
}
return maxi_mod ;
}
// 使用牛顿迭代法计算一个矩阵的近似逆
double gctl : : newton_inverse ( const spmat < double > & in_mat , _2d_matrix & inverse_mat ,
double epsilon , int iter_times , bool initiate )
{
if ( in_mat . empty ( ) )
throw runtime_error ( " The input matrix is empty. Thrown by gctl::newton_inverse(...) " ) ;
if ( in_mat . row_size ( ) ! = in_mat . col_size ( ) )
throw logic_error ( " The input matrix is square. Thrown by gctl::newton_inverse(...) " ) ;
if ( iter_times < 0 )
throw invalid_argument ( " Invalid iteration times. Thrown by gctl::newton_inverse(...) " ) ;
int m_size = in_mat . row_size ( ) ;
if ( initiate )
{
// 初始化逆矩阵 使用输入矩阵的对角元素构建初始矩阵
if ( ! inverse_mat . empty ( ) ) inverse_mat . clear ( ) ;
inverse_mat . resize ( m_size , m_size , 0.0 ) ;
for ( int i = 0 ; i < m_size ; i + + )
{
inverse_mat [ i ] [ i ] = 1.0 / in_mat . at ( i , i ) ;
}
}
if ( inverse_mat . row_size ( ) ! = m_size | | inverse_mat . col_size ( ) ! = m_size )
throw logic_error ( " Invalid output matrix size. From gctl::newton_inverse(...) " ) ;
// 迭代的收敛条件 || E - in_mat*inverse_mat ||_inf < 1
// 计算矩阵的无穷大范数
double maxi_mod = 0.0 , mod , ele ;
array < double > tmp_arr ( m_size , 0.0 ) ; // A*X 的列向量
for ( int i = 0 ; i < m_size ; i + + )
{
mod = 0.0 ;
for ( int j = 0 ; j < m_size ; j + + )
{
for ( int k = 0 ; k < m_size ; k + + )
{
tmp_arr [ k ] = inverse_mat [ k ] [ j ] ;
}
ele = in_mat . multiply_vector ( tmp_arr , i ) ;
if ( i = = j )
{
mod + = GCTL_FABS ( 1.0 - ele ) ;
}
else
{
mod + = GCTL_FABS ( ele ) ;
}
}
maxi_mod = GCTL_MAX ( maxi_mod , mod ) ;
}
if ( maxi_mod > = 1.0 )
{
GCTL_ShowWhatError ( " The iteration may not converge. From gctl::newton_inverse(...) " ,
GCTL_WARNING_ERROR , 0 , 0 , 0 ) ;
}
array < double > col_ax ( m_size , 0.0 ) ;
_2d_matrix tmp_mat ( m_size , m_size , 0.0 ) ;
for ( int t = 0 ; t < iter_times ; t + + )
{
if ( maxi_mod < = epsilon )
break ;
//else std::cout << "epsilon = " << maxi_mod << std::endl;
for ( int i = 0 ; i < m_size ; i + + )
{
for ( int j = 0 ; j < m_size ; j + + )
{
tmp_mat [ i ] [ j ] = inverse_mat [ i ] [ j ] ;
}
}
for ( int n = 0 ; n < m_size ; n + + )
{
for ( int i = 0 ; i < m_size ; i + + )
{
for ( int j = 0 ; j < m_size ; j + + )
{
for ( int k = 0 ; k < m_size ; k + + )
{
tmp_arr [ k ] = tmp_mat [ k ] [ i ] ;
}
col_ax [ j ] = in_mat . multiply_vector ( tmp_arr , j ) ;
col_ax [ j ] * = - 1.0 ;
}
col_ax [ i ] + = 2.0 ;
ele = 0.0 ;
for ( int j = 0 ; j < m_size ; j + + )
{
ele + = tmp_mat [ n ] [ j ] * col_ax [ j ] ;
}
inverse_mat [ n ] [ i ] = ele ;
}
}
maxi_mod = 0.0 ;
for ( int i = 0 ; i < m_size ; i + + )
{
mod = 0.0 ;
for ( int j = 0 ; j < m_size ; j + + )
{
for ( int k = 0 ; k < m_size ; k + + )
{
tmp_arr [ k ] = inverse_mat [ k ] [ j ] ;
}
ele = in_mat . multiply_vector ( tmp_arr , i ) ;
if ( i = = j )
{
mod + = GCTL_FABS ( 1.0 - ele ) ;
}
else
{
mod + = GCTL_FABS ( ele ) ;
}
}
maxi_mod = GCTL_MAX ( maxi_mod , mod ) ;
}
}
return maxi_mod ;
}
void gctl : : schmidt_orthogonal ( const array < double > & a , array < double > & e , int a_s )
{
if ( a . empty ( ) )
throw runtime_error ( " The input array is empty. Thrown by gctl::schmidt_orthogonal(...) " ) ;
if ( a_s < = 1 ) // a_s >= 2
throw invalid_argument ( " vector size must be bigger than one. Thrown by gctl::schmidt_orthogonal(...) " ) ;
int t_s = a . size ( ) ;
if ( t_s % a_s ! = 0 | | t_s < = 3 ) // t_s >= 4
throw invalid_argument ( " incompatible total array size. Thrown by gctl::schmidt_orthogonal(...) " ) ;
int len = t_s / a_s ;
if ( len < a_s )
throw invalid_argument ( " the vectors are over-determined. Thrown by gctl::schmidt_orthogonal(...) " ) ;
e . resize ( t_s , 0.0 ) ;
double ae , ee ;
for ( int i = 0 ; i < a_s ; i + + )
{
for ( int l = 0 ; l < len ; l + + )
{
e [ l + i * len ] = a [ l + i * len ] ;
}
for ( int m = 0 ; m < i ; m + + )
{
ae = ee = 0.0 ;
for ( int n = 0 ; n < len ; n + + )
{
ae + = a [ n + i * len ] * e [ n + m * len ] ;
ee + = e [ n + m * len ] * e [ n + m * len ] ;
}
for ( int n = 0 ; n < len ; n + + )
{
e [ n + i * len ] - = e [ n + m * len ] * ae / ee ;
}
}
}
for ( int i = 0 ; i < a_s ; i + + )
{
ee = 0.0 ;
for ( int l = 0 ; l < len ; l + + )
{
ee + = e [ l + i * len ] * e [ l + i * len ] ;
}
ee = sqrt ( ee ) ;
for ( int l = 0 ; l < len ; l + + )
{
e [ l + i * len ] / = ee ;
}
}
return ;
}
2024-09-10 15:45:07 +08:00
double gctl : : dist_inverse_weight ( std : : vector < double > * dis_vec , std : : vector < double > * val_vec , int order )
{
if ( dis_vec - > size ( ) ! = val_vec - > size ( ) )
throw runtime_error ( " The arrays have different sizes. Thrown by gctl::dist_inverse_weight(...) " ) ;
double total_dist = 0 ;
for ( int i = 0 ; i < dis_vec - > size ( ) ; i + + )
{
dis_vec - > at ( i ) = 1.0 / ( GCTL_ZERO + pow ( dis_vec - > at ( i ) , order ) ) ;
total_dist + = dis_vec - > at ( i ) ;
}
double ret = 0.0 ;
for ( int i = 0 ; i < dis_vec - > size ( ) ; i + + )
{
ret + = val_vec - > at ( i ) * dis_vec - > at ( i ) / total_dist ;
}
return ret ;
}
int gctl : : find_index ( const double * in_array , int array_size , double in_val , int & index )
{
if ( array_size < = 0 )
{
index = - 1 ;
return - 1 ;
}
else if ( array_size = = 1 )
{
index = - 1 ;
return - 1 ;
}
else if ( in_val < in_array [ 0 ] | | in_val > in_array [ array_size - 1 ] )
{
index = - 1 ;
return - 1 ;
}
else if ( array_size = = 2 )
{
index = 0 ;
return 0 ;
}
else
{
int low_range = 0 ;
int high_range = array_size - 1 ;
int test_index ;
bool found = false ;
while ( high_range - low_range > = 1 )
{
test_index = floor ( 0.5 * ( low_range + high_range ) ) ;
if ( in_val > = in_array [ test_index ] & & in_val < = in_array [ test_index + 1 ] )
{
index = test_index ;
found = true ;
break ;
}
else if ( in_val < in_array [ test_index ] )
{
high_range = test_index ;
}
else if ( in_val > in_array [ test_index + 1 ] )
{
low_range = test_index + 1 ;
}
}
if ( found ) return 0 ;
else return - 1 ;
}
}
int gctl : : find_index ( array < double > * in_array , double in_val , int & index )
{
return find_index ( in_array - > get ( ) , in_array - > size ( ) , in_val , index ) ;
}
void gctl : : fractal_model_1d ( array < double > & out_arr , int out_size , double l_val ,
double r_val , double maxi_range , double smoothness )
{
if ( out_size < = 0 )
throw invalid_argument ( " Negative output size. Thrown by gctl::fractal_model_1d(...) " ) ;
if ( maxi_range < = 0 )
throw invalid_argument ( " Negative maximal range. Thrown by gctl::fractal_model_1d(...) " ) ;
if ( smoothness < = 0 )
throw invalid_argument ( " Negative smoothness. Thrown by gctl::fractal_model_1d(...) " ) ;
out_arr . resize ( out_size ) ;
int bigger_num = ( int ) pow ( 2 , ceil ( log ( out_arr . size ( ) - 1 ) / log ( 2 ) ) ) + 1 ;
array < double > tmp_arr ( bigger_num ) ; // 计算的长度必须为2的次方数
int step_size = ( int ) ( bigger_num - 1 ) / 2 ;
tmp_arr [ 0 ] = l_val ;
tmp_arr [ bigger_num - 1 ] = r_val ;
srand ( time ( 0 ) ) ;
while ( step_size > = 1 )
{
for ( int i = step_size ; i < bigger_num ; i + = 2 * step_size )
{
tmp_arr [ i ] = random ( - 1.0 * maxi_range , maxi_range ) +
0.5 * ( tmp_arr [ i - step_size ] + tmp_arr [ i + step_size ] ) ;
}
maxi_range = pow ( 2.0 , - 1.0 * smoothness ) * maxi_range ;
step_size / = 2 ;
}
for ( int i = 0 ; i < out_arr . size ( ) ; i + + )
{
out_arr [ i ] = tmp_arr [ i ] ;
}
return ;
}
void gctl : : fractal_model_2d ( _2d_matrix & out_arr , int r_size , int c_size , double dl_val ,
double dr_val , double ul_val , double ur_val , double maxi_range , double smoothness ,
unsigned int seed )
{
if ( r_size < = 0 | | c_size < = 0 )
throw invalid_argument ( " Negative output size. Thrown by gctl::fractal_model_2d(...) " ) ;
if ( maxi_range < = 0 )
throw invalid_argument ( " Negative maximal range. Thrown by gctl::fractal_model_2d(...) " ) ;
if ( smoothness < = 0 )
throw invalid_argument ( " Negative smoothness. Thrown by gctl::fractal_model_2d(...) " ) ;
int i , j , m , n , R , jmax ;
double random_d ;
out_arr . resize ( r_size , c_size ) ;
int xnum = out_arr . col_size ( ) ;
int ynum = out_arr . row_size ( ) ;
int order_x = ceil ( log ( xnum - 1 ) / log ( 2 ) ) ;
int order_y = ceil ( log ( ynum - 1 ) / log ( 2 ) ) ;
int imax = GCTL_MAX ( order_x , order_y ) ;
int ntotal = ( int ) pow ( 2.0 , imax ) + 1 ; //总数据点数为2的imax次方加1
_2d_matrix topo ( ntotal , ntotal , 0.0 ) ;
for ( i = 0 ; i < ntotal ; i + + ) //设定地形数据初始值,角点数据必须给出
{
for ( j = 0 ; j < ntotal ; j + + )
{
if ( i = = 0 & & j = = 0 )
{
topo [ i ] [ j ] = ul_val ; //角点初始值;
}
else if ( i = = ntotal - 1 & & j = = 0 )
{
topo [ i ] [ j ] = dl_val ; //角点初始值;
}
else if ( i = = 0 & & j = = ntotal - 1 )
{
topo [ i ] [ j ] = ur_val ; //角点初始值;
}
else if ( i = = ntotal - 1 & & j = = ntotal - 1 )
{
topo [ i ] [ j ] = dr_val ; //角点初始值;
}
else
{
topo [ i ] [ j ] = GCTL_BDL_MAX ;
}
}
}
if ( seed = = 0 ) srand ( time ( 0 ) ) ;
else srand ( seed ) ;
for ( i = 1 ; i < = imax ; i + + ) //开始迭代,生成正方形区域随机地形
{
R = int ( double ( ntotal - 1 ) / pow ( 2.0 , i ) ) ;
jmax = int ( pow ( 4.0 , i - 1 ) ) ;
for ( j = 1 ; j < = jmax ; j + + )
{
random_d = random ( - 1.0 * maxi_range , maxi_range ) ;
m = 2 * R * ( j - ( ceil ( ( double ) j / pow ( 2.0 , i - 1 ) ) - 1 ) * pow ( 2.0 , i - 1 ) ) - R ;
n = 2 * R * ( ceil ( ( double ) j / pow ( 2.0 , i - 1 ) ) ) - R ;
topo [ m ] [ n ] = ( topo [ m - R ] [ n - R ] + topo [ m + R ] [ n - R ] + topo [ m - R ] [ n + R ] + topo [ m + R ] [ n + R ] ) / 4 + random_d ;
}
for ( j = 1 ; j < = jmax ; j + + )
{
m = 2 * R * ( j - ( ceil ( ( double ) j / pow ( 2.0 , i - 1 ) ) - 1 ) * pow ( 2.0 , i - 1 ) ) - R ;
n = 2 * R * ( ceil ( ( double ) j / pow ( 2.0 , i - 1 ) ) ) - R ;
if ( topo [ m ] [ n - R ] = = GCTL_BDL_MAX )
{
random_d = random ( - 1.0 * maxi_range , maxi_range ) ;
if ( ( n - R ) ! = 0 )
{
topo [ m ] [ n - R ] = ( topo [ m ] [ n - 2 * R ] + topo [ m - R ] [ n - R ] + topo [ m + R ] [ n - R ] + topo [ m ] [ n ] ) / 4 + random_d ;
}
else
{
topo [ m ] [ n - R ] = ( topo [ m - R ] [ n - R ] + topo [ m + R ] [ n - R ] + topo [ m ] [ n ] ) / 3 + random_d ;
}
}
if ( topo [ m - R ] [ n ] = = GCTL_BDL_MAX )
{
random_d = random ( - 1.0 * maxi_range , maxi_range ) ;
if ( ( m - R ) ! = 0 )
{
topo [ m - R ] [ n ] = ( topo [ m - R ] [ n - R ] + topo [ m - 2 * R ] [ n ] + topo [ m ] [ n ] + topo [ m - R ] [ n + R ] ) / 4 + random_d ;
}
else
{
topo [ m - R ] [ n ] = ( topo [ m - R ] [ n - R ] + topo [ m ] [ n ] + topo [ m - R ] [ n + R ] ) / 3 + random_d ;
}
}
if ( topo [ m + R ] [ n ] = = GCTL_BDL_MAX )
{
random_d = random ( - 1.0 * maxi_range , maxi_range ) ;
if ( ( m + R ) ! = ( ntotal - 1 ) )
{
topo [ m + R ] [ n ] = ( topo [ m + R ] [ n - R ] + topo [ m ] [ n ] + topo [ m + 2 * R ] [ n ] + topo [ m + R ] [ n + R ] ) / 4 + random_d ;
}
else
{
topo [ m + R ] [ n ] = ( topo [ m + R ] [ n - R ] + topo [ m ] [ n ] + topo [ m + R ] [ n + R ] ) / 3 + random_d ;
}
}
if ( topo [ m ] [ n + R ] = = GCTL_BDL_MAX )
{
random_d = random ( - 1.0 * maxi_range , maxi_range ) ;
if ( ( n + R ) ! = ( ntotal - 1 ) )
{
topo [ m ] [ n + R ] = ( topo [ m ] [ n ] + topo [ m - R ] [ n + R ] + topo [ m + R ] [ n + R ] + topo [ m ] [ n + 2 * R ] ) / 4 + random_d ;
}
else
{
topo [ m ] [ n + R ] = ( topo [ m ] [ n ] + topo [ m - R ] [ n + R ] + topo [ m + R ] [ n + R ] ) / 3 + random_d ;
}
}
}
maxi_range = pow ( 2.0 , - 1.0 * smoothness ) * maxi_range ;
}
for ( int j = 0 ; j < ynum ; j + + ) //按预设区域剪裁数组
{
for ( int i = 0 ; i < xnum ; i + + )
{
out_arr [ i ] [ j ] = topo [ i ] [ j ] ;
}
}
return ;
}
void gctl : : difference_1d ( const array < double > & in , array < double > & diff , double spacing , int order )
{
if ( order < 1 | | order > 4 )
throw invalid_argument ( " The input order can only be 1 to 4. Thrown by gctl::difference_1d(...) " ) ;
if ( spacing < = 0.0 )
throw invalid_argument ( " The input spacing can't be negative or zero. Thrown by void gctl::difference_1d(...) " ) ;
if ( order = = 1 & & in . size ( ) < 3 )
throw runtime_error ( " The input array size must be equal to or bigger than three for the first order derivative. Thrown by gctl::difference_1d(...) " ) ;
if ( order = = 2 & & in . size ( ) < 4 )
throw runtime_error ( " The input array size must be equal to or bigger than four for the second order derivative. Thrown by gctl::difference_1d(...) " ) ;
if ( order = = 3 & & in . size ( ) < 6 )
throw runtime_error ( " The input array size must be equal to or bigger than six for the third order derivative. Thrown by gctl::difference_1d(...) " ) ;
if ( order = = 4 & & in . size ( ) < 7 )
throw runtime_error ( " The input array size must be equal to or bigger than seven for the fourth order derivative. Thrown by gctl::difference_1d(...) " ) ;
int t_size = in . size ( ) ;
diff . resize ( t_size ) ;
// 利用向前或向后差分计算边缘元素的导数
if ( order = = 1 )
{
diff [ 0 ] = ( - 3.0 * in [ 0 ] + 4.0 * in [ 1 ] - in [ 2 ] ) / ( 2.0 * spacing ) ;
diff [ t_size - 1 ] = ( 3.0 * in [ t_size - 1 ] - 4.0 * in [ t_size - 2 ] + in [ t_size - 3 ] ) / ( 2.0 * spacing ) ;
for ( int i = 1 ; i < t_size - 1 ; i + + )
{
diff [ i ] = ( in [ i + 1 ] - in [ i - 1 ] ) / ( 2.0 * spacing ) ;
}
}
else if ( order = = 2 )
{
diff [ 0 ] = ( 2.0 * in [ 0 ] - 5.0 * in [ 1 ] + 4.0 * in [ 2 ] - in [ 3 ] ) / ( spacing * spacing ) ;
diff [ t_size - 1 ] = ( 2.0 * in [ t_size - 1 ] - 5.0 * in [ t_size - 2 ] + 4.0 * in [ t_size - 3 ] - in [ t_size - 4 ] ) / ( spacing * spacing ) ;
for ( int i = 1 ; i < t_size - 1 ; i + + )
{
diff [ i ] = ( in [ i - 1 ] - 2.0 * in [ i ] + in [ i + 1 ] ) / ( spacing * spacing ) ;
}
}
else if ( order = = 3 )
{
diff [ 0 ] = ( - 5.0 * in [ 0 ] + 18.0 * in [ 1 ] - 24.0 * in [ 2 ] + 14.0 * in [ 3 ] - 3.0 * in [ 4 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ 1 ] = ( - 5.0 * in [ 1 ] + 18.0 * in [ 2 ] - 24.0 * in [ 3 ] + 14.0 * in [ 4 ] - 3.0 * in [ 5 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ t_size - 1 ] = ( 5.0 * in [ t_size - 1 ] - 18.0 * in [ t_size - 2 ] + 24.0 * in [ t_size - 3 ] - 14.0 * in [ t_size - 4 ] + 3.0 * in [ t_size - 5 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ t_size - 2 ] = ( 5.0 * in [ t_size - 2 ] - 18.0 * in [ t_size - 3 ] + 24.0 * in [ t_size - 4 ] - 14.0 * in [ t_size - 5 ] + 3.0 * in [ t_size - 6 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
for ( int i = 2 ; i < t_size - 2 ; i + + )
{
diff [ i ] = ( - 1.0 * in [ i - 2 ] + 2.0 * in [ i - 1 ] - 2.0 * in [ i + 1 ] + in [ i + 2 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
}
}
else
{
diff [ 0 ] = ( 3.0 * in [ 0 ] - 14.0 * in [ 1 ] + 26.0 * in [ 2 ] - 24.0 * in [ 3 ] + 11.0 * in [ 4 ] - 2.0 * in [ 5 ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ 1 ] = ( 3.0 * in [ 1 ] - 14.0 * in [ 2 ] + 26.0 * in [ 3 ] - 24.0 * in [ 4 ] + 11.0 * in [ 5 ] - 2.0 * in [ 6 ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ t_size - 1 ] = ( 3.0 * in [ t_size - 1 ] - 14.0 * in [ t_size - 2 ] + 26.0 * in [ t_size - 3 ] - 24.0 * in [ t_size - 4 ] + 11.0 * in [ t_size - 5 ] - 2.0 * in [ t_size - 6 ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ t_size - 2 ] = ( 3.0 * in [ t_size - 2 ] - 14.0 * in [ t_size - 3 ] + 26.0 * in [ t_size - 4 ] - 24.0 * in [ t_size - 5 ] + 11.0 * in [ t_size - 6 ] - 2.0 * in [ t_size - 7 ] ) / ( spacing * spacing * spacing * spacing ) ;
for ( int i = 2 ; i < t_size - 2 ; i + + )
{
diff [ i ] = ( in [ i - 2 ] - 4.0 * in [ i - 1 ] + 6.0 * in [ i ] - 4.0 * in [ i + 1 ] + in [ i + 2 ] ) / ( spacing * spacing * spacing * spacing ) ;
}
}
return ;
}
void gctl : : difference_2d ( const _2d_matrix & in , _2d_matrix & diff , double spacing , gradient_type_e d_type , int order )
{
std : : string err_str ;
if ( order < 1 | | order > 4 )
throw invalid_argument ( " The input order can only be 1 to 4. Thrown by void gctl::difference_2d(...) " ) ;
if ( spacing < = 0.0 )
throw invalid_argument ( " The input spacing can't be negative or zero. Thrown by void gctl::difference_2d(...) " ) ;
int t_size ;
if ( d_type = = Dx )
{
t_size = in . col_size ( ) ;
}
else if ( d_type = = Dy )
{
t_size = in . row_size ( ) ;
}
else
{
throw logic_error ( " The calculation type must be Dx or Dy. Thrown by gctl::difference_2d(...) " ) ;
}
if ( order = = 1 & & t_size < 3 )
throw runtime_error ( " The input array size must be equal to or bigger than 3x3 for the first order derivative. Thrown by void gctl::difference_2d(...) " ) ;
if ( order = = 2 & & t_size < 4 )
throw runtime_error ( " The input array size must be equal to or bigger than 4x4 for the second order derivative. Thrown by gctl::difference_2d(...) " ) ;
if ( order = = 3 & & t_size < 6 )
throw runtime_error ( " The input array size must be equal to or bigger than 6x6 for the third order derivative. Thrown by gctl::difference_2d(...) " ) ;
if ( order = = 4 & & t_size < 7 )
throw runtime_error ( " The input array size must be equal to or bigger than 7x7 for the fourth order derivative. Thrown by void gctl::difference_2d(...) " ) ;
int tr_size = in . row_size ( ) , tl_size = in . col_size ( ) ;
diff . resize ( tr_size , tl_size ) ;
if ( d_type = = Dx )
{
if ( order = = 1 )
{
for ( int i = 0 ; i < tr_size ; i + + )
{
diff [ i ] [ 0 ] = ( - 3.0 * in [ i ] [ 0 ] + 4.0 * in [ i ] [ 1 ] - in [ i ] [ 2 ] ) / ( 2.0 * spacing ) ;
diff [ i ] [ tl_size - 1 ] = ( 3.0 * in [ i ] [ tl_size - 1 ] - 4.0 * in [ i ] [ tl_size - 2 ] + in [ i ] [ tl_size - 3 ] ) / ( 2.0 * spacing ) ;
for ( int j = 1 ; j < tl_size - 1 ; j + + )
{
diff [ i ] [ j ] = ( in [ i ] [ j + 1 ] - in [ i ] [ j - 1 ] ) / ( 2.0 * spacing ) ;
}
}
}
else if ( order = = 2 )
{
for ( int i = 0 ; i < tr_size ; i + + )
{
diff [ i ] [ 0 ] = ( 2.0 * in [ i ] [ 0 ] - 5.0 * in [ i ] [ 1 ] + 4.0 * in [ i ] [ 2 ] - in [ i ] [ 3 ] ) / ( spacing * spacing ) ;
diff [ i ] [ tl_size - 1 ] = ( 2.0 * in [ i ] [ tl_size - 1 ] - 5.0 * in [ i ] [ tl_size - 2 ] + 4.0 * in [ i ] [ tl_size - 3 ] - in [ i ] [ tl_size - 4 ] ) / ( spacing * spacing ) ;
for ( int j = 1 ; j < tl_size - 1 ; j + + )
{
diff [ i ] [ j ] = ( in [ i ] [ j - 1 ] - 2.0 * in [ i ] [ j ] + in [ i ] [ j + 1 ] ) / ( spacing * spacing ) ;
}
}
}
else if ( order = = 3 )
{
for ( int i = 0 ; i < tr_size ; i + + )
{
diff [ i ] [ 0 ] = ( - 5.0 * in [ i ] [ 0 ] + 18.0 * in [ i ] [ 1 ] - 24.0 * in [ i ] [ 2 ] + 14.0 * in [ i ] [ 3 ] - 3.0 * in [ i ] [ 4 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ i ] [ 1 ] = ( - 5.0 * in [ i ] [ 1 ] + 18.0 * in [ i ] [ 2 ] - 24.0 * in [ i ] [ 3 ] + 14.0 * in [ i ] [ 4 ] - 3.0 * in [ i ] [ 5 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ i ] [ tl_size - 1 ] = ( 5.0 * in [ i ] [ tl_size - 1 ] - 18.0 * in [ i ] [ tl_size - 2 ] + 24.0 * in [ i ] [ tl_size - 3 ] - 14.0 * in [ i ] [ tl_size - 4 ] + 3.0 * in [ i ] [ tl_size - 5 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ i ] [ tl_size - 2 ] = ( 5.0 * in [ i ] [ tl_size - 2 ] - 18.0 * in [ i ] [ tl_size - 3 ] + 24.0 * in [ i ] [ tl_size - 4 ] - 14.0 * in [ i ] [ tl_size - 5 ] + 3.0 * in [ i ] [ tl_size - 6 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
for ( int j = 2 ; j < tl_size - 2 ; j + + )
{
diff [ i ] [ j ] = ( - 1.0 * in [ i ] [ j - 2 ] + 2.0 * in [ i ] [ j - 1 ] - 2.0 * in [ i ] [ j + 1 ] + in [ i ] [ j + 2 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
}
}
}
else
{
for ( int i = 0 ; i < tr_size ; i + + )
{
diff [ i ] [ 0 ] = ( 3.0 * in [ i ] [ 0 ] - 14.0 * in [ i ] [ 1 ] + 26.0 * in [ i ] [ 2 ] - 24.0 * in [ i ] [ 3 ] + 11.0 * in [ i ] [ 4 ] - 2.0 * in [ i ] [ 5 ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ i ] [ 1 ] = ( 3.0 * in [ i ] [ 1 ] - 14.0 * in [ i ] [ 2 ] + 26.0 * in [ i ] [ 3 ] - 24.0 * in [ i ] [ 4 ] + 11.0 * in [ i ] [ 5 ] - 2.0 * in [ i ] [ 6 ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ i ] [ tl_size - 1 ] = ( 3.0 * in [ i ] [ tl_size - 1 ] - 14.0 * in [ i ] [ tl_size - 2 ] + 26.0 * in [ i ] [ tl_size - 3 ] - 24.0 * in [ i ] [ tl_size - 4 ] + 11.0 * in [ i ] [ tl_size - 5 ] - 2.0 * in [ i ] [ tl_size - 6 ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ i ] [ tl_size - 2 ] = ( 3.0 * in [ i ] [ tl_size - 2 ] - 14.0 * in [ i ] [ tl_size - 3 ] + 26.0 * in [ i ] [ tl_size - 4 ] - 24.0 * in [ i ] [ tl_size - 5 ] + 11.0 * in [ i ] [ tl_size - 6 ] - 2.0 * in [ i ] [ tl_size - 7 ] ) / ( spacing * spacing * spacing * spacing ) ;
for ( int j = 2 ; j < tl_size - 2 ; j + + )
{
diff [ i ] [ j ] = ( in [ i ] [ j - 2 ] - 4.0 * in [ i ] [ j - 1 ] + 6.0 * in [ i ] [ j ] - 4.0 * in [ i ] [ j + 1 ] + in [ i ] [ j + 2 ] ) / ( spacing * spacing * spacing * spacing ) ;
}
}
}
}
else
{
if ( order = = 1 )
{
for ( int j = 0 ; j < tl_size ; j + + )
{
diff [ 0 ] [ j ] = ( - 3.0 * in [ 0 ] [ j ] + 4.0 * in [ 1 ] [ j ] - in [ 2 ] [ j ] ) / ( 2.0 * spacing ) ;
diff [ tr_size - 1 ] [ j ] = ( 3.0 * in [ tr_size - 1 ] [ j ] - 4.0 * in [ tr_size - 2 ] [ j ] + in [ tr_size - 3 ] [ j ] ) / ( 2.0 * spacing ) ;
for ( int i = 1 ; i < tr_size - 1 ; i + + )
{
diff [ i ] [ j ] = ( in [ i + 1 ] [ j ] - in [ i - 1 ] [ j ] ) / ( 2.0 * spacing ) ;
}
}
}
else if ( order = = 2 )
{
for ( int j = 0 ; j < tl_size ; j + + )
{
diff [ 0 ] [ j ] = ( 2.0 * in [ 0 ] [ j ] - 5.0 * in [ 1 ] [ j ] + 4.0 * in [ 2 ] [ j ] - in [ 3 ] [ j ] ) / ( spacing * spacing ) ;
diff [ tr_size - 1 ] [ j ] = ( 2.0 * in [ tr_size - 1 ] [ j ] - 5.0 * in [ tr_size - 2 ] [ j ] + 4.0 * in [ tr_size - 3 ] [ j ] - in [ tr_size - 4 ] [ j ] ) / ( spacing * spacing ) ;
for ( int i = 1 ; i < tr_size - 1 ; i + + )
{
diff [ i ] [ j ] = ( in [ i - 1 ] [ j ] - 2.0 * in [ i ] [ j ] + in [ i + 1 ] [ j ] ) / ( spacing * spacing ) ;
}
}
}
else if ( order = = 3 )
{
for ( int j = 0 ; j < tl_size ; j + + )
{
diff [ 0 ] [ j ] = ( - 5.0 * in [ 0 ] [ j ] + 18.0 * in [ 1 ] [ j ] - 24.0 * in [ 2 ] [ j ] + 14.0 * in [ 3 ] [ j ] - 3.0 * in [ 4 ] [ j ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ 1 ] [ j ] = ( - 5.0 * in [ 1 ] [ j ] + 18.0 * in [ 2 ] [ j ] - 24.0 * in [ 3 ] [ j ] + 14.0 * in [ 4 ] [ j ] - 3.0 * in [ 5 ] [ j ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ tr_size - 1 ] [ j ] = ( 5.0 * in [ tr_size - 1 ] [ j ] - 18.0 * in [ tr_size - 2 ] [ j ] + 24.0 * in [ tr_size - 3 ] [ j ] - 14.0 * in [ tr_size - 4 ] [ j ] + 3.0 * in [ tr_size - 5 ] [ j ] ) / ( 2.0 * spacing * spacing * spacing ) ;
diff [ tr_size - 2 ] [ j ] = ( 5.0 * in [ tr_size - 2 ] [ j ] - 18.0 * in [ tr_size - 3 ] [ j ] + 24.0 * in [ tr_size - 4 ] [ j ] - 14.0 * in [ tr_size - 5 ] [ j ] + 3.0 * in [ tr_size - 6 ] [ j ] ) / ( 2.0 * spacing * spacing * spacing ) ;
for ( int i = 2 ; i < tr_size - 2 ; i + + )
{
diff [ i ] [ j ] = ( - 1.0 * in [ i - 2 ] [ j ] + 2.0 * in [ i - 1 ] [ j ] - 2.0 * in [ i + 1 ] [ j ] + in [ i + 2 ] [ j ] ) / ( 2.0 * spacing * spacing * spacing ) ;
}
}
}
else
{
for ( int j = 0 ; j < tl_size ; j + + )
{
diff [ 0 ] [ j ] = ( 3.0 * in [ 0 ] [ j ] - 14.0 * in [ 1 ] [ j ] + 26.0 * in [ 2 ] [ j ] - 24.0 * in [ 3 ] [ j ] + 11.0 * in [ 4 ] [ j ] - 2.0 * in [ 5 ] [ j ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ 1 ] [ j ] = ( 3.0 * in [ 1 ] [ j ] - 14.0 * in [ 2 ] [ j ] + 26.0 * in [ 3 ] [ j ] - 24.0 * in [ 4 ] [ j ] + 11.0 * in [ 5 ] [ j ] - 2.0 * in [ 6 ] [ j ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ tr_size - 1 ] [ j ] = ( 3.0 * in [ tr_size - 1 ] [ j ] - 14.0 * in [ tr_size - 2 ] [ j ] + 26.0 * in [ tr_size - 3 ] [ j ] - 24.0 * in [ tr_size - 4 ] [ j ] + 11.0 * in [ tr_size - 5 ] [ j ] - 2.0 * in [ tr_size - 6 ] [ j ] ) / ( spacing * spacing * spacing * spacing ) ;
diff [ tr_size - 2 ] [ j ] = ( 3.0 * in [ tr_size - 2 ] [ j ] - 14.0 * in [ tr_size - 3 ] [ j ] + 26.0 * in [ tr_size - 4 ] [ j ] - 24.0 * in [ tr_size - 5 ] [ j ] + 11.0 * in [ tr_size - 6 ] [ j ] - 2.0 * in [ tr_size - 7 ] [ j ] ) / ( spacing * spacing * spacing * spacing ) ;
for ( int i = 2 ; i < tr_size - 2 ; i + + )
{
diff [ i ] [ j ] = ( in [ i - 2 ] [ j ] - 4.0 * in [ i - 1 ] [ j ] + 6.0 * in [ i ] [ j ] - 4.0 * in [ i + 1 ] [ j ] + in [ i + 2 ] [ j ] ) / ( spacing * spacing * spacing * spacing ) ;
}
}
}
}
return ;
}
void gctl : : difference_2d ( const array < double > & in , array < double > & diff , int row_size , int col_size ,
double spacing , gradient_type_e d_type , int order )
{
std : : string err_str ;
if ( order < 1 | | order > 4 )
throw invalid_argument ( " The input order can only be 1 to 4. Thrown by void gctl::difference_2d(...) " ) ;
if ( spacing < = 0.0 )
throw invalid_argument ( " The input spacing can't be negative or zero. Thrown by void gctl::difference_2d(...) " ) ;
if ( row_size * col_size ! = in . size ( ) )
throw invalid_argument ( " The input array size does not match. Thrown by void gctl::difference_2d(...) " ) ;
int t_size ;
if ( d_type = = Dx )
{
t_size = col_size ;
}
else if ( d_type = = Dy )
{
t_size = row_size ;
}
else
{
throw logic_error ( " The calculation type must be Dx or Dy. Thrown by gctl::difference_2d(...) " ) ;
}
if ( order = = 1 & & t_size < 3 )
throw runtime_error ( " The input array size must be equal to or bigger than 3x3 for the first order derivative. Thrown by gctl::difference_2d(...) " ) ;
if ( order = = 2 & & t_size < 4 )
throw runtime_error ( " The input array size must be equal to or bigger than 4x4 for the second order derivative. Thrown by gctl::difference_2d(...) " ) ;
if ( order = = 3 & & t_size < 6 )
throw runtime_error ( " The input array size must be equal to or bigger than 6x6 for the third order derivative. Thrown by gctl::difference_2d(...) " ) ;
if ( order = = 4 & & t_size < 7 )
throw runtime_error ( " The input array size must be equal to or bigger than 7x7 for the fourth order derivative. Thrown by gctl::difference_2d(...) " ) ;
int tr_size = row_size , tl_size = col_size ;
diff . resize ( tr_size * tl_size ) ;
int idx ;
if ( d_type = = Dx )
{
if ( order = = 1 )
{
for ( int i = 0 ; i < tr_size ; i + + )
{
idx = i * tl_size ;
diff [ idx ] = ( - 3.0 * in [ idx ] + 4.0 * in [ idx + 1 ] - in [ idx + 2 ] ) / ( 2.0 * spacing ) ;
idx = i * tl_size + tl_size - 1 ;
diff [ idx ] = ( 3.0 * in [ idx ] - 4.0 * in [ idx - 1 ] + in [ idx - 2 ] ) / ( 2.0 * spacing ) ;
for ( int j = 1 ; j < tl_size - 1 ; j + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( in [ idx + 1 ] - in [ idx - 1 ] ) / ( 2.0 * spacing ) ;
}
}
}
else if ( order = = 2 )
{
for ( int i = 0 ; i < tr_size ; i + + )
{
idx = i * tl_size ;
diff [ idx ] = ( 2.0 * in [ idx ] - 5.0 * in [ idx + 1 ] + 4.0 * in [ idx + 2 ] - in [ idx + 3 ] ) / ( spacing * spacing ) ;
idx = i * tl_size + tl_size - 1 ;
diff [ idx ] = ( 2.0 * in [ idx ] - 5.0 * in [ idx - 1 ] + 4.0 * in [ idx - 2 ] - in [ idx - 3 ] ) / ( spacing * spacing ) ;
for ( int j = 1 ; j < tl_size - 1 ; j + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( in [ idx - 1 ] - 2.0 * in [ idx ] + in [ idx + 1 ] ) / ( spacing * spacing ) ;
}
}
}
else if ( order = = 3 )
{
for ( int i = 0 ; i < tr_size ; i + + )
{
idx = i * tl_size ;
diff [ idx ] = ( - 5.0 * in [ idx ] + 18.0 * in [ idx + 1 ] - 24.0 * in [ idx + 2 ] + 14.0 * in [ idx + 3 ] - 3.0 * in [ idx + 4 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
idx = i * tl_size + 1 ;
diff [ idx ] = ( - 5.0 * in [ idx ] + 18.0 * in [ idx + 1 ] - 24.0 * in [ idx + 2 ] + 14.0 * in [ idx + 3 ] - 3.0 * in [ idx + 4 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
idx = i * tl_size + tl_size - 1 ;
diff [ idx ] = ( 5.0 * in [ idx ] - 18.0 * in [ idx - 1 ] + 24.0 * in [ idx - 2 ] - 14.0 * in [ idx - 3 ] + 3.0 * in [ idx - 4 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
idx = i * tl_size + tl_size - 2 ;
diff [ idx ] = ( 5.0 * in [ idx ] - 18.0 * in [ idx - 1 ] + 24.0 * in [ idx - 2 ] - 14.0 * in [ idx - 3 ] + 3.0 * in [ idx - 4 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
for ( int j = 2 ; j < tl_size - 2 ; j + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( - 1.0 * in [ idx - 2 ] + 2.0 * in [ idx - 1 ] - 2.0 * in [ idx + 1 ] + in [ idx + 2 ] ) / ( 2.0 * spacing * spacing * spacing ) ;
}
}
}
else
{
for ( int i = 0 ; i < tr_size ; i + + )
{
idx = i * tl_size ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx + 1 ] + 26.0 * in [ idx + 2 ] - 24.0 * in [ idx + 3 ] + 11.0 * in [ idx + 4 ] - 2.0 * in [ idx + 5 ] ) / ( spacing * spacing * spacing * spacing ) ;
idx = i * tl_size + 1 ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx + 1 ] + 26.0 * in [ idx + 2 ] - 24.0 * in [ idx + 3 ] + 11.0 * in [ idx + 4 ] - 2.0 * in [ idx + 5 ] ) / ( spacing * spacing * spacing * spacing ) ;
idx = i * tl_size + tl_size - 1 ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx - 1 ] + 26.0 * in [ idx - 2 ] - 24.0 * in [ idx - 3 ] + 11.0 * in [ idx - 4 ] - 2.0 * in [ idx - 5 ] ) / ( spacing * spacing * spacing * spacing ) ;
idx = i * tl_size + tl_size - 2 ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx - 1 ] + 26.0 * in [ idx - 2 ] - 24.0 * in [ idx - 3 ] + 11.0 * in [ idx - 4 ] - 2.0 * in [ idx - 5 ] ) / ( spacing * spacing * spacing * spacing ) ;
for ( int j = 2 ; j < tl_size - 2 ; j + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( in [ idx - 2 ] - 4.0 * in [ idx - 1 ] + 6.0 * in [ idx ] - 4.0 * in [ idx + 1 ] + in [ idx + 2 ] ) / ( spacing * spacing * spacing * spacing ) ;
}
}
}
}
else
{
if ( order = = 1 )
{
for ( int j = 0 ; j < tl_size ; j + + )
{
idx = j ;
diff [ idx ] = ( - 3.0 * in [ idx ] + 4.0 * in [ idx + tl_size ] - in [ idx + 2 * tl_size ] ) / ( 2.0 * spacing ) ;
idx = ( tr_size - 1 ) * tl_size + j ;
diff [ idx ] = ( 3.0 * in [ idx ] - 4.0 * in [ idx - tl_size ] + in [ idx - 2 * tl_size ] ) / ( 2.0 * spacing ) ;
for ( int i = 1 ; i < tr_size - 1 ; i + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( in [ idx + tl_size ] - in [ idx - tl_size ] ) / ( 2.0 * spacing ) ;
}
}
}
else if ( order = = 2 )
{
for ( int j = 0 ; j < tl_size ; j + + )
{
idx = j ;
diff [ idx ] = ( 2.0 * in [ idx ] - 5.0 * in [ idx + tl_size ] + 4.0 * in [ idx + 2 * tl_size ] - in [ idx + 3 * tl_size ] ) / ( spacing * spacing ) ;
idx = ( tr_size - 1 ) * tl_size + j ;
diff [ idx ] = ( 2.0 * in [ idx ] - 5.0 * in [ idx - tl_size ] + 4.0 * in [ idx - 2 * tl_size ] - in [ idx - 3 * tl_size ] ) / ( spacing * spacing ) ;
for ( int i = 1 ; i < tr_size - 1 ; i + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( in [ idx - tl_size ] - 2.0 * in [ idx ] + in [ idx + tl_size ] ) / ( spacing * spacing ) ;
}
}
}
else if ( order = = 3 )
{
for ( int j = 0 ; j < tl_size ; j + + )
{
idx = j ;
diff [ idx ] = ( - 5.0 * in [ idx ] + 18.0 * in [ idx + tl_size ] - 24.0 * in [ idx + 2 * tl_size ] + 14.0 * in [ idx + 3 * tl_size ] - 3.0 * in [ idx + 4 * tl_size ] ) / ( 2.0 * spacing * spacing * spacing ) ;
idx = tl_size + j ;
diff [ idx ] = ( - 5.0 * in [ idx ] + 18.0 * in [ idx + tl_size ] - 24.0 * in [ idx + 2 * tl_size ] + 14.0 * in [ idx + 3 * tl_size ] - 3.0 * in [ idx + 4 * tl_size ] ) / ( 2.0 * spacing * spacing * spacing ) ;
idx = ( tr_size - 1 ) * tl_size + j ;
diff [ idx ] = ( 5.0 * in [ idx ] - 18.0 * in [ idx - tl_size ] + 24.0 * in [ idx - 2 * tl_size ] - 14.0 * in [ idx - 3 * tl_size ] + 3.0 * in [ idx - 4 * tl_size ] ) / ( 2.0 * spacing * spacing * spacing ) ;
idx = ( tr_size - 2 ) * tl_size + j ;
diff [ idx ] = ( 5.0 * in [ idx ] - 18.0 * in [ idx - tl_size ] + 24.0 * in [ idx - 2 * tl_size ] - 14.0 * in [ idx - 3 * tl_size ] + 3.0 * in [ idx - 4 * tl_size ] ) / ( 2.0 * spacing * spacing * spacing ) ;
for ( int i = 2 ; i < tr_size - 2 ; i + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( - 1.0 * in [ idx - 2 * tl_size ] + 2.0 * in [ idx - tl_size ] - 2.0 * in [ idx + tl_size ] + in [ idx + 2 * tl_size ] ) / ( 2.0 * spacing * spacing * spacing ) ;
}
}
}
else
{
for ( int j = 0 ; j < tl_size ; j + + )
{
idx = j ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx + tl_size ] + 26.0 * in [ idx + 2 * tl_size ] - 24.0 * in [ idx + 3 * tl_size ] + 11.0 * in [ idx + 4 * tl_size ] - 2.0 * in [ idx + 5 * tl_size ] ) / ( spacing * spacing * spacing * spacing ) ;
idx = tl_size + j ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx + tl_size ] + 26.0 * in [ idx + 2 * tl_size ] - 24.0 * in [ idx + 3 * tl_size ] + 11.0 * in [ idx + 4 * tl_size ] - 2.0 * in [ idx + 5 * tl_size ] ) / ( spacing * spacing * spacing * spacing ) ;
idx = ( tr_size - 1 ) * tl_size + j ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx - tl_size ] + 26.0 * in [ idx - 2 * tl_size ] - 24.0 * in [ idx - 3 * tl_size ] + 11.0 * in [ idx - 4 * tl_size ] - 2.0 * in [ idx - 5 * tl_size ] ) / ( spacing * spacing * spacing * spacing ) ;
idx = ( tr_size - 2 ) * tl_size + j ;
diff [ idx ] = ( 3.0 * in [ idx ] - 14.0 * in [ idx - tl_size ] + 26.0 * in [ idx - 2 * tl_size ] - 24.0 * in [ idx - 3 * tl_size ] + 11.0 * in [ idx - 4 * tl_size ] - 2.0 * in [ idx - 5 * tl_size ] ) / ( spacing * spacing * spacing * spacing ) ;
for ( int i = 2 ; i < tr_size - 2 ; i + + )
{
idx = i * tl_size + j ;
diff [ idx ] = ( in [ idx - 2 * tl_size ] - 4.0 * in [ idx - tl_size ] + 6.0 * in [ idx ] - 4.0 * in [ idx + tl_size ] + in [ idx + 2 * tl_size ] ) / ( spacing * spacing * spacing * spacing ) ;
}
}
}
}
return ;
}