基础条件:Windows系统,clion,msvc C++工具链,GNU Scientific Library
到GSL官网https://www.gnu.org/software/gsl/ 下载 源代码文件,解压到硬盘中,我的路径为 G:\software\gsl28。先建立一个config.h文件放到G:\software\gsl28下面,内容为
cpp
/* config.h manually created for MSVC on Windows */
/* 启用内联函数支持 */
#define HAVE_INLINE 1
#ifdef _MSC_VER
#define inline __inline
#endif
/* 标准头文件存在 */
#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_STDINT_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_SYS_TYPES_H 1
/* 标准库函数存在 */
#define HAVE_MEMCPY 1
#define HAVE_MEMMOVE 1
#define HAVE_STRDUP 1
#define HAVE_STRTOL 1
#define HAVE_STRTOUL 1
#define HAVE_VPRINTF 1
/* 数学函数声明存在(MSVC 提供这些函数) */
#define HAVE_DECL_HYPOT 1
#define HAVE_DECL_LOG1P 1
#define HAVE_DECL_EXPM1 1
#define HAVE_DECL_ACOSH 1
#define HAVE_DECL_ASINH 1
#define HAVE_DECL_ATANH 1
#define HAVE_DECL_LDEXP 1
#define HAVE_DECL_FREXP 1
#define HAVE_DECL_ISINF 1
#define HAVE_DECL_ISFINITE 1
#define HAVE_DECL_FINITE 1
#define HAVE_DECL_ISNAN 1
/* 选择 IEEE 接口(x86 架构) */
#define HAVE_GNUX86_IEEE_INTERFACE 1
/* C89 标准头文件都可用 */
#define STDC_HEADERS 1
/* 包信息 */
#define PACKAGE "gsl"
#define VERSION "2.7"
#define PACKAGE_BUGREPORT ""
/* stdlib.h 中有 EXIT_SUCCESS/EXIT_FAILURE */
#define HAVE_EXIT_SUCCESS_AND_FAILURE 1
/* 启用 SSE 扩展(x86 处理器) */
#define HAVE_FPU_X86_SSE 1
/* 无扩展精度寄存器(MSVC 不适用) */
/* #undef HAVE_EXTENDED_PRECISION_REGISTERS */
/* 定义 GSL_COERCE_DBL */
#ifdef HAVE_EXTENDED_PRECISION_REGISTERS
#define GSL_COERCE_DBL(x) (gsl_coerce_double(x))
#else
#define GSL_COERCE_DBL(x) (x)
#endif
/* 忽略丢弃指针的警告 */
#define DISCARD_POINTER(p) /* ignoring discarded pointer */
/* 默认启用范围检查(可以注释掉以关闭) */
/* #define GSL_RANGE_CHECK 0 */
/* 空指针检查 */
#define RETURN_IF_NULL(x) if (!x) { return ; }
#ifndef GSL_VAR
#define GSL_VAR extern
#endif
CMakeLists.txt内容如下:
cpp
cmake_minimum_required(VERSION 3.30)
project(GSLnonlinearequations)
# 启用 C 语言支持
enable_language(C)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 99) # 为 C 代码设置 C99 标准
set(GSL_ROOT "G:/software/gsl28")
#收集所有源文件(递归所有子目录,但排除测试文件)
file(GLOB_RECURSE GSL_SOURCES
"${GSL_ROOT}/sys/*.c"
"${GSL_ROOT}/err/*.c"
"${GSL_ROOT}/cblas/*.c"
"${GSL_ROOT}/blas/*.c"
"${GSL_ROOT}/vector/*.c"
"${GSL_ROOT}/matrix/*.c"
"${GSL_ROOT}/permutation/*.c"
"${GSL_ROOT}/complex/*.c"
"${GSL_ROOT}/block/*.c"
"${GSL_ROOT}/linalg/*.c"
"${GSL_ROOT}/multiroots/*.c"
"${GSL_ROOT}/min/*.c"
"${GSL_ROOT}/poly/*.c"
"${GSL_ROOT}/fit/*.c"
"${GSL_ROOT}/statistics/*.c"
"${GSL_ROOT}/rng/*.c"
"${GSL_ROOT}/randist/*.c"
# "${GSL_ROOT}/ieee-utils/*.c"
"${GSL_ROOT}/test/*.c"
"${GSL_ROOT}/roots/*.c"
# 这里自己添加你需要的源文件
)
# 排除测试文件(通常包含 test 或 -test 的文件)
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/test.*\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/tests.*\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/bench.*\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/.*_source\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/apply_givens\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/cholesky_common\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/svdstep\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/dogleg\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/enorm\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/poly/balance\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/poly/companion\\.c$")
list(FILTER GSL_SOURCES EXCLUDE REGEX ".*/poly/qr\\.c$")
# 首先在构建目录中创建 gsl 文件夹
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/gsl")
# 查找所有模块下的 gsl_*.h 头文件
file(GLOB_RECURSE GSL_HEADERS "${GSL_ROOT}/*/gsl*.h" "${GSL_ROOT}/gsl*.h" )
# 将每个头文件复制到构建目录的 gsl/ 下
foreach(header ${GSL_HEADERS})
get_filename_component(name ${header} NAME)
configure_file(${header} "${CMAKE_CURRENT_BINARY_DIR}/gsl/${name}" COPYONLY)
endforeach()
# 创建 GSL 静态库
# -------------------------------------------------------------------
add_library(gsl_static STATIC ${GSL_SOURCES})
# 设置包含路径:
# - 构建目录下的 gsl/(用于外部包含 #include <gsl/...>)
# - 源码根目录(因为库内部可能会引用其他模块的头文件,如 #include <gsl_vector.h>)
target_include_directories(gsl_static PUBLIC
"${CMAKE_CURRENT_BINARY_DIR}"
"${GSL_ROOT}"
)
# 对于 MSVC,关闭一些安全警告
if(MSVC)
target_compile_definitions(gsl_static PRIVATE _CRT_SECURE_NO_WARNINGS HAVE_CONFIG_H)
# 告诉 MSVC 将文件作为 C 代码编译(避免 C++ 名称修饰)
set_target_properties(gsl_static PROPERTIES LINKER_LANGUAGE C)
endif()
add_executable(GSLnonlinearequations main.cpp)
target_link_libraries(GSLnonlinearequations gsl_static)
# 同样为主程序添加包含路径(以便 #include <gsl/gsl_vector.h> 能找到)
target_include_directories(GSLnonlinearequations PRIVATE
"${CMAKE_CURRENT_BINARY_DIR}"
)
main.cpp文件内容如下:
cpp
#include <stdio.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_multiroots.h>
#include <gsl/gsl_roots.h>
// -------------------- 辅助函数:封装一维求根(Brent 方法)--------------------
double root_brent(gsl_function F, double lo, double hi, double epsrel) {
const gsl_root_fsolver_type *T = gsl_root_fsolver_brent;
gsl_root_fsolver *s = gsl_root_fsolver_alloc(T);
gsl_root_fsolver_set(s, &F, lo, hi);
int status;
size_t iter = 0;
double root;
do {
iter++;
gsl_root_fsolver_iterate(s);
root = gsl_root_fsolver_root(s);
lo = gsl_root_fsolver_x_lower(s);
hi = gsl_root_fsolver_x_upper(s);
status = gsl_root_test_interval(lo, hi, 0, epsrel);
} while (status == GSL_CONTINUE && iter < 1000);
printf("迭代次数 = %zu, 状态 = %s\n", iter, gsl_strerror(status));
gsl_root_fsolver_free(s);
return root;
}
// -------------------- 辅助函数:封装通用多维方程组求解(Hybrids 方法)--------------------
void multiroot_hybrids(gsl_multiroot_function F, gsl_vector *x, double epsabs) {
const gsl_multiroot_fsolver_type *T = gsl_multiroot_fsolver_hybrids;
gsl_multiroot_fsolver *s = gsl_multiroot_fsolver_alloc(T, F.n);
gsl_multiroot_fsolver_set(s, &F, x);
int status;
size_t iter = 0;
do {
iter++;
status = gsl_multiroot_fsolver_iterate(s);
if (status) break;
status = gsl_multiroot_test_residual(s->f, epsabs);
} while (status == GSL_CONTINUE && iter < 1000);
printf("迭代次数 = %zu, 状态 = %s\n", iter, gsl_strerror(status));
// 打印所有未知数的解
printf("解: ");
for (size_t i = 0; i < F.n; ++i) {
printf("x%zu = %.8f ", i, gsl_vector_get(s->x, i));
}
printf("\n");
// 打印所有残差
printf("残差: ");
for (size_t i = 0; i < F.n; ++i) {
printf("f%zu = %.2e ", i, gsl_vector_get(s->f, i));
}
printf("\n");
gsl_multiroot_fsolver_free(s);
}
// -------------------- 问题定义 --------------------
//一元方程 x^2 - 5 = 0
double square_minus_five(double x, void *params) {
return x * x - 5.0;
}
// 一元方程 cos(x) = x
double cos_minus_x(double x, void *params) {
(void)params; // 未使用参数
return cos(x) - x;
}
// Rosenbrock 方程组: a(1-x0)=0, b(x1-x0^2)=0
struct rparams { double a, b; };
int rosenbrock_f(const gsl_vector *x, void *params, gsl_vector *f) {
double a = ((struct rparams *)params)->a;
double b = ((struct rparams *)params)->b;
double x0 = gsl_vector_get(x, 0);
double x1 = gsl_vector_get(x, 1);
gsl_vector_set(f, 0, a * (1 - x0));
gsl_vector_set(f, 1, b * (x1 - x0 * x0));
return GSL_SUCCESS;
}
// 二元 Powell 病态方程组: 10000x1x2-1=0, e^(-x1)+e^(-x2)-1.0001=0
struct powell_params { double dummy; };
int powell_f(const gsl_vector *x, void *params, gsl_vector *f) {
double x0 = gsl_vector_get(x, 0);
double x1 = gsl_vector_get(x, 1);
gsl_vector_set(f, 0, 10000.0 * x0 * x1 - 1.0);
gsl_vector_set(f, 1, exp(-x0) + exp(-x1) - 1.0001);
return GSL_SUCCESS;
}
// 三元 Helical 方程组(螺旋谷函数):
int helical_f(const gsl_vector *x, void *params, gsl_vector *f) {
double x0 = gsl_vector_get(x, 0);
double x1 = gsl_vector_get(x, 1);
double x2 = gsl_vector_get(x, 2);
double theta;
if (x0 > 0)
theta = atan(x1 / x0) / (2 * M_PI);
else if (x0 < 0)
theta = 0.5 + atan(x1 / x0) / (2 * M_PI);
else
theta = (x1 > 0) ? 0.25 : -0.25;
gsl_vector_set(f, 0, 10.0 * (x2 - 10.0 * theta));
gsl_vector_set(f, 1, 10.0 * (sqrt(x0 * x0 + x1 * x1) - 1.0));
gsl_vector_set(f, 2, x2);
return GSL_SUCCESS;
}
// 四元 Powell 奇异方程组
int powellsing_f(const gsl_vector *x, void *params, gsl_vector *f) {
double x0 = gsl_vector_get(x, 0);
double x1 = gsl_vector_get(x, 1);
double x2 = gsl_vector_get(x, 2);
double x3 = gsl_vector_get(x, 3);
gsl_vector_set(f, 0, x0 + 10.0 * x1);
gsl_vector_set(f, 1, sqrt(5.0) * (x2 - x3));
gsl_vector_set(f, 2, pow(x1 - 2.0 * x2, 2.0));
gsl_vector_set(f, 3, sqrt(10.0) * pow(x0 - x3, 2.0));
return GSL_SUCCESS;
}
// -------------------- 主函数--------------------
int main() {
// 1. 求解一元方程 x^2 - 5 = 0
gsl_function F1 = {square_minus_five, NULL};
double root1 = root_brent(F1, 0.0, 5.0, 1e-7);
printf("一元方程 x^2-5=0 的解: x = %.8f\n\n", root1);
// 2. 求解一元方程 cos(x) = x
gsl_function F2 = {cos_minus_x, NULL};
double root2 = root_brent(F2, 0.0, 1.0, 1e-7);
printf("一元方程 cos(x)=x 的解: x = %.8f\n\n", root2);
// 3. 求解二元 Rosenbrock 方程组
struct rparams p = {1.0, 10.0};
gsl_multiroot_function F_rosen = {rosenbrock_f, 2, &p};
gsl_vector *x_rosen = gsl_vector_alloc(2);
gsl_vector_set(x_rosen, 0, 10.0);
gsl_vector_set(x_rosen, 1, 100000.0);
printf("Rosenbrock 方程组求解:\n");
multiroot_hybrids(F_rosen, x_rosen, 1e-7);
gsl_vector_free(x_rosen);
printf("\n");
// 4. 求解二元 Powell 病态方程组
gsl_multiroot_function F_powell = {powell_f, 2, NULL};
gsl_vector *x_powell = gsl_vector_alloc(2);
gsl_vector_set(x_powell, 0, 0.0);
gsl_vector_set(x_powell, 1, 1.0);
printf("Powell 病态方程组求解:\n");
multiroot_hybrids(F_powell, x_powell, 1e-7);
gsl_vector_free(x_powell);
printf("\n");
// 5. 求解三元 Helical 方程组
gsl_multiroot_function F_helical = {helical_f, 3, NULL};
gsl_vector *x_helical = gsl_vector_alloc(3);
gsl_vector_set(x_helical, 0, -1.0);
gsl_vector_set(x_helical, 1, 0.0);
gsl_vector_set(x_helical, 2, 0.0);
printf("Helical 方程组求解:\n");
multiroot_hybrids(F_helical, x_helical, 1e-7);
gsl_vector_free(x_helical);
printf("\n");
// 6. 求解四元 Powell 奇异方程组
gsl_multiroot_function F_sing = {powellsing_f, 4, NULL};
gsl_vector *x_sing = gsl_vector_alloc(4);
gsl_vector_set(x_sing, 0, 3.0);
gsl_vector_set(x_sing, 1, -1.0);
gsl_vector_set(x_sing, 2, 0.0);
gsl_vector_set(x_sing, 3, 1.0);
printf("Powell 奇异方程组求解:\n");
multiroot_hybrids(F_sing, x_sing, 1e-7);
gsl_vector_free(x_sing);
return 0;
}
运行结果如下:


附录:



