⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsl-design.texi

📁 math library from gnu
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
@node Persistence, Using Return Values, Exceptions and Error handling, Design@section PersistenceIf you make an object foo which uses blocks of memory (e.g. vector,matrix, histogram) you can provide functions for reading and writingthose blocks,@smallexampleint gsl_foo_fread (FILE * stream, gsl_foo * v);int gsl_foo_fwrite (FILE * stream, const gsl_foo * v);int gsl_foo_fscanf (FILE * stream, gsl_foo * v);int gsl_foo_fprintf (FILE * stream, const gsl_foo * v, const char *format);@end smallexample@noindentOnly dump out the blocks of memory, not any associated parameters suchas lengths.  The idea is for the user to build higher level input/outputfacilities using the functions the library provides.  The fprintf/fscanfversions should be portable between architectures, while the binaryversions should be the "raw" version of the data. Use the functions@smallexampleint gsl_block_fread (FILE * stream, gsl_block * b);int gsl_block_fwrite (FILE * stream, const gsl_block * b);int gsl_block_fscanf (FILE * stream, gsl_block * b);int gsl_block_fprintf (FILE * stream, const gsl_block * b, const char *format);@end smallexample@noindentor@smallexampleint gsl_block_raw_fread (FILE * stream, double * b, size_t n, size_t stride);int gsl_block_raw_fwrite (FILE * stream, const double * b, size_t n, size_t stride);int gsl_block_raw_fscanf (FILE * stream, double * b, size_t n, size_t stride);int gsl_block_raw_fprintf (FILE * stream, const double * b, size_t n, size_t stride, const char *format);@end smallexample@noindentto do the actual reading and writing.@node Using Return Values, Variable Names, Persistence, Design@section Using Return ValuesAlways assign a return value to a variable before using it.  This allowseasier debugging of the function, and inspection and modification of thereturn value.  If the variable is only needed temporarily then encloseit in a suitable scope.For example, instead of writing,@examplea = f(g(h(x,y)))@end example@noindentuse temporary variables to store the intermediate values,@example@{  double u = h(x,y);  double v = g(u);  a = f(v);@}@end example@noindentThese can then be inspected more easily in the debugger, and breakpointscan be placed more precisely.  The compiler will eliminate the temporaryvariables automatically when the program is compiled with optimization.@node Variable Names, Datatype widths, Using Return Values, Design@section Variable NamesTry to follow existing conventions for variable names,@table @code@item dimnumber of dimensions@item wpointer to workspace @item statepointer to state variable (use @code{s} if you need to save characters)@item resultpointer to result (output variable)@item abserrabsolute error @item relerrrelative error@item epsabsabsolute tolerance @item epsrelrelative tolerance@item sizethe size of an array or vector e.g. double array[size] @item stridethe stride of a vector@item size1the number of rows in a matrix@item size2the number of columns in a matrix@item ngeneral integer number, e.g. number of elements of array, in fft, etc@item rrandom number generator (gsl_rng)@end table@node Datatype widths, size_t, Variable Names, Design@section Datatype widthsBe aware that in ANSI C the type @code{int} is only guaranteed toprovide 16-bits. It may provide more, but is not guaranteed to.Therefore if you require 32 bits you must use @code{long int}, whichwill have 32 bits or more.  Of course, on many platforms the type@code{int} does have 32 bits instead of 16 bits but we have to code tothe ANSI standard rather than a specific platform.@node size_t, Arrays vs Pointers, Datatype widths, Design@section size_tAll objects (blocks of memory, etc) should be measured in terms of a@code{size_t} type.  Therefore any iterations (e.g. @code{for(i=0; i<N;i++)}) should also use an index of type @code{size_t}.  Don't mix @code{int} and @code{size_t}.  They are @emph{not}interchangeable.If you need to write a descending loop you have to be careful because@code{size_t} is unsigned, so instead of@examplefor (i = N - 1; i >= 0; i--) @{ ... @} /* DOESN'T WORK */@end example@noindentuse something like@examplefor (i = N; i-- > 0;) @{ ... @}@end example@noindentto avoid problems with wrap-around at @code{i=0}.  Note that thepost-decrement ensures that the loop variable is tested before itreaches zero.  Beware that @code{i} will wraparound on exit from theloop.  (This could also be written as @code{for (i = N; i--;)} sincethe test for @code{i>0} is equivalent to @code{i!=0} for an unsignedinteger)If you really want to avoid confusion use a separate variable to invertthe loop order,@examplefor (i = 0; i < N; i++) @{ j = N - i; ... @}@end exampleNote (BJG). Originally, I suggested using@examplefor (i = N; i > 0 && i--;) @{ ... @}@end examplewhich makes the test for @code{i>0} explicit and leaves @code{i=0} onexit from the loop.  However, it is slower as there is an additionalbranch which prevents unrolling.  Thanks to J. Seward for pointingthis out.Note: As a matter of style, please use post-increment (@code{i++}) andpost-decrement (@code{i--}) operators by default and only usepre-increment (@code{++i}) and pre-decrement (@code{--i}) operatorswhere specifically needed.@node Arrays vs Pointers, Pointers, size_t, Design@section Arrays vs PointersA function can be declared with either pointer arguments or arrayarguments.  The C standard considers these to be equivalent. However, itis useful to distinguish between the case of a pointer, representing asingle object which is being modified, and an array which represents aset of objects with unit stride (that are modified or not depending onthe presence of @code{const}).  For vectors, where the stride is notrequired to be unity, the pointer form is preferred.@smallexample/* real value, set on output */int foo (double * x);                           /* real vector, modified */int foo (double * x, size_t stride, size_t n);  /* constant real vector */int foo (const double * x, size_t stride, size_t n);  /* real array, modified */int bar (double x[], size_t n);                 /* real array, not modified */int baz (const double x[], size_t n);           @end smallexample@node  Pointers, Constness, Arrays vs Pointers, Design@section PointersAvoid dereferencing pointers on the right-hand side of an expression wherepossible.  It's better to introduce a temporary variable.  This iseasier for the compiler to optimise and also more readable since itavoids confusion between the use of @code{*} for multiplication anddereferencing.@examplewhile (fabs (f) < 0.5)@{  *e = *e - 1;  f  *= 2;@}@end example@noindentis better written as,@example@{   int p = *e;  while (fabs(f) < 0.5)    @{     p--;     f *= 2;    @}  *e = p;@}@end example@node Constness, Pseudo-templates, Pointers, Design@section ConstnessUse @code{const} in function prototypes wherever an object pointed to bya pointer is constant (obviously).  For variables which are meaningfullyconstant within a function/scope use @code{const} also.  This preventsyou from accidentally modifying a variable which should be constant(e.g. length of an array, etc).  It can also help the compiler dooptimization.  These comments also apply to arguments passed by valuewhich should be made @code{const} when that is meaningful.@node Pseudo-templates, Arbitrary Constants, Constness, Design@section Pseudo-templatesThere are some pseudo-template macros available in @file{templates_on.h}and @file{templates_off.h}.  See a directory link @file{block} fordetails on how to use them.  Use sparingly, they are a bit of anightmare, but unavoidable in places.In particular, the convention is: templates are used for operations on"data" only (vectors, matrices, statistics, sorting).  This is intendedto cover the case where the program must interface with an externaldata-source which produces a fixed type. e.g. a big array of char'sproduced by an 8-bit counter.All other functions can use double, for floating point, or theappropriate integer type for integers (e.g. unsigned long int for randomnumbers).  It is not the intention to provide a fully templated versionof the library. That would be "putting a quart into a pint pot". To summarize, almosteverything should be in a "natural type" which is appropriate fortypical usage, and templates are there to handle a few cases where it isunavoidable that other data-types will be encountered.For floating point work "double" is considered a "natural type".  Thissort of idea is a part of the C language.@node  Arbitrary Constants, Test suites, Pseudo-templates, Design@section Arbitrary ConstantsAvoid arbitrary constants.For example, don't hard code "small" values like '1e-30', '1e-100' or@code{10*GSL_DBL_EPSILON} into the routines.  This is not appropriatefor a general purpose library.Compute values accurately using IEEE arithmetic.  If errors arepotentially significant then error terms should be estimated reliablyand returned to the user, by analytically deriving an error propagationformula, not using guesswork.A careful consideration of the algorithm usually shows that arbitraryconstants are unnecessary, and represent an important parameter whichshould be accessible to the user.For example, consider the following code:@exampleif (residual < 1e-30) @{   return 0.0;  /* residual is zero within round-off error */@}@end example@noindentThis should be rewritten as,@example   return residual;@end example@noindentin order to allow the user to determine whether the residual is significant or not.The only place where it is acceptable to use constants like@code{GSL_DBL_EPSILON} is in function approximations, (e.g. taylorseries, asymptotic expansions, etc).  In these cases it is not anarbitrary constant, but an inherent part of the algorithm.@node Test suites, Compilation, Arbitrary Constants, Design@section Test suitesThe implementor of each module should provide a reasonable test suitefor the routines.The test suite should be a program that uses the library and checks theresult against known results, or invokes the library several times anddoes a statistical analysis on the results (for example in the case ofrandom number generators).Ideally the one test program per directory should aim for 100% pathcoverage of the code.  Obviously it would be a lot of work to really

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -