inline struct map_type *multiplicate( struct map_type *map, struct map_type *map_2 ) { int i, j, k; __float128 sum_tmp; struct map_type *result; if( ( map->i_size == 1 && map->j_size == 1 ) && ( map_2->i_size > 1 || map_2->j_size > 1 ) ) { result = multiplicate_on_value( *( *( map->memory + 0 ) + 0 ), map_2 ); } else { result = allocate( map->i_size, map_2->j_size ); for( i = 0; i < map->i_size; i++ ) { for( j = 0; j < map_2->j_size; j++ ) { for( sum_tmp = 0, k = 0; k < map->j_size; k++ ) { sum_tmp += *( *( map->memory + i ) + k ) * ( *( *( map_2->memory + k ) + j ) ); } *( *( result->memory + i ) + j ) = sum_tmp; } } } return result; }
inline struct map_type *subtraction( struct map_type *map, struct map_type *map_2 ) { struct map_type *tmp, *result; tmp = multiplicate_on_value( -1, map_2 ); result = addition( map, tmp ); deallocate( tmp ); return result; }
inline struct map_type *get_inverse( struct map_type *map ) { struct map_type *result; if( map->i_size == 1 && map->j_size == 1 ) { result = allocate( 2, 2 ); result->i_size = 1; result->j_size = 1; __float128 value = *( *( map->memory + 0 ) + 0 ); *( *( result->memory + 0 ) + 0 ) = value == 0 ? 0 : powf( value, -1 ); } else { __float128 determinant = get_determinant( map ); result = multiplicate_on_value( powf( determinant, -1 ), map ); } return result; }
struct map_type *dfp( function func, struct map_type *map_x, __float128 grad_toler, __float128 fx_toler, const unsigned int max_iter ) { unsigned int iter; __float128 lambda, result_func_value, temp_func_value; struct map_type *result, *b, *grad1, *tmp, *s, *grad2, *g, *tmp2, *tmp3, *d, *x1, *x2, *x3, *x4, *x5; result = NULL; result_func_value = func( map_x ); b = get_identity_matrix( map_x->j_size ); grad1 = first_derivatives( func, map_x ); tmp = transposition( grad1 ); deallocate( grad1 ); grad1 = tmp; for( iter = 0 ; iter < max_iter; iter++ ) { tmp = multiplicate_on_value( -1, b ); s = multiplicate( tmp, grad1 ); deallocate( tmp ); tmp = transposition( s ); tmp2 = multiplicate_on_value( powf( get_euclidean_distance( s ), -1 ), tmp ); deallocate( s ); deallocate( tmp ); s = tmp2; lambda = 1; lambda = line_search( func, map_x, lambda, s ); d = multiplicate_on_value( lambda, s ); tmp = addition( map_x, d ); deallocate( d ); deallocate( map_x ); map_x = tmp; temp_func_value = func( map_x ); if( result_func_value > temp_func_value ) { iter = 0; result_func_value = temp_func_value; if( result != NULL ) { deallocate( result ); } result = clone( map_x ); } grad2 = first_derivatives( func, map_x ); tmp = transposition( grad2 ); deallocate( grad2 ); grad2 = tmp; g = subtraction( grad2, grad1 ); deallocate( grad1 ); grad1 = grad2; if( get_euclidean_distance( grad1 ) < grad_toler ) { /// TODO: Нужно очистить память break; } tmp = transposition( s ); x1 = multiplicate( s, tmp ); x2 = multiplicate( s, g ); deallocate( s ); deallocate( tmp ); tmp = multiplicate_on_value( lambda, x1 ); tmp2 = get_inverse( x2 ); tmp3 = multiplicate( tmp, tmp2 ); deallocate( tmp ); tmp = addition( b, tmp3 ); deallocate( x1 ); deallocate( x2 ); deallocate( tmp2 ); deallocate( tmp3 ); deallocate( b ); b = tmp; x3 = multiplicate( b, g ); tmp = transposition( b ); x4 = multiplicate( tmp, g ); deallocate( tmp ); tmp = transposition( g ); tmp2 = multiplicate( tmp, b ); x5 = multiplicate( tmp2, g ); deallocate( g ); deallocate( tmp ); deallocate( tmp2 ); tmp = transposition( x4 ); tmp2 = multiplicate( x3, tmp ); deallocate( tmp ); tmp = get_inverse( x5 ); tmp3 = multiplicate( tmp, tmp2 ); deallocate( tmp ); tmp = subtraction( b, tmp3 ); deallocate( b ); b = tmp; deallocate( tmp2 ); deallocate( tmp3 ); deallocate( x3 ); deallocate( x4 ); deallocate( x5 ); } return result; }