# dy_vector.h

Go to the documentation of this file.

    00001 /*
    00002   This file is a part of the Dylp LP distribution.
    00003
    00004         Copyright (C) 2005 -- 2007 Lou Hafer
    00005
    00006         School of Computing Science
    00007         Simon Fraser University
    00008         Burnaby, B.C., V5A 1S6, Canada
    00009         lou@cs.sfu.ca
    00010
    00011   This code is licensed under the terms of the Eclipse Public License (EPL).
    00012 */
    00013
    00014 #ifndef _DYLP_VECTOR_H
    00015 #define _DYLP_VECTOR_H
    00016
    00017 /* The part that requires information from the private header file config.h
    00018  * is only needed for building DyLP itself, so we only do this if DYLP_INTERNAL
    00019  * had been defined.
    00020  */
    00021 #ifdef DYLP_INTERNAL
    00022
    00023 /*
    00024   @(#)dy_vector.h         4.5         11/06/04
    00025   svn/cvs: $Id: dy_vector.h 436 2011-06-08 21:06:45Z stefan $
    00026 */
    00027
    00028 #include <DylpConfig.h>
    00029
    00030 /*
    00031   Why, you might ask, are we including ctype.h? Well, it's required by the
    00032   ANSI C specification, so it's pretty well guaranteed to exist. And, at least
    00033   in Solaris and Linux environments that I'm familiar with, it'll pull in the
    00034   compile-time symbols that specify big- or little-endian, which we really
    00035   want.
    00036 */
    00037 #include <ctype.h>
    00038
    00039 /*
    00040   A bunch of standard definitions.
    00041 */
    00042 #include "dylib_std.h"
    00043
    00044 /*
    00045   In a few rare instances, the declarations here will be unused, but for dylp
    00046   this is a good bet.
    00047 */
    00048 #include <math.h>
    00049
    00050 /*
    00051   Some subset of these will work on any system. Check config_dylp.h to see
    00052   which ones are actually in use.
    00053 */
    00054 #ifdef HAVE_FLOAT_H
    00055 # include <float.h>
    00056 #endif
    00057 #ifdef HAVE_IEEEFP_H
    00058 # include <ieeefp.h>
    00059 #endif
    00060 #ifdef HAVE_SUNMATH_H
    00061 # include <sunmath.h>
    00062 #endif
    00063
    00064
    00065 /*
    00066   The Theory: quiet_nan is used to indicate failure (by returning NaN)
    00067   without triggering a signal the client may not be prepared to catch. The
    00068   idea is that any reasonable checks in the client will detect NaN fairly
    00069   quickly.  signalling_nan is used when there's no advantage in delaying a
    00070   signal.
    00071
    00072   The Reality: Neither seems to trigger a signal, and many computing
    00073   environments can't tell the difference. But it's coded into dylp, and it'd
    00074   be much ado to change. Hence the compile-time ugliness that follows.
    00075
    00076   In the Sun Workshop environment, quiet_nan and signalling_nan are declared
    00077   in sunmath.h and found in libsunmath. With release 5.0, sunmath.h includes
    00078   some declarations of type `long long', which isn't supported under the -Xc
    00079   (strict ANSI compatibility) option for cc. So, we extract only the
    00080   definitions we need.  Unfortunately, sunmath.h is present only in the Sun
    00081   Workshop programming environment. Sun without Workshop has only the
    00082   require file nan.h, which is inadequate.
    00083
    00084   For a long while, GNU C didn't distinguish QNaN and SNaN. More recently,
    00085   its support for IEEE 754 seems to have improved, but it's not clear that we
    00086   can count on everyone having a recent GCC environment just yet. Here, too,
    00087   nan.h is inadequate.  The easy way out is to simply #define them as macros
    00088   that return the proper bit pattern. Arguably this would make more sense in
    00089   general than Sun's implementation as functions.
    00090
    00091   According to IEEE 754, the proper bit patterns are:
    00092
    00093     0x7ff00000 00000000                  for Inf
    00094     0x7fffffff ffffffff                  for QNaN
    00095     0x7ff00000 00000001                  for SNaN
    00096
    00097   It works this way: The IEEE definition of NaN is
    00098     Bits         Value
    00099     63           sign --- don't care for a NaN, but nice to be positive (0)
    00100     62:52        exponent --- must be maximum value, 0x7ff
    00101     51:0         fraction --- must not be zero (a fraction of zero is the
    00102                  representation of infinity). Sun documentation defines QNaN
    00103                  as having bit 51 of the fraction set to 1, SNaN as having
    00104                  bit 51 set to 0.
    00105
    00106   Creating the proper constants qualifies as a serious gross hack. And if you
    00107   have a little-endian machine (the 80x86 family being far and away the most
    00108   common example), you need to flip the byte order.
    00109 */
    00110   typedef union { unsigned char fpchr[8] ; double fpdbl ; } fpunion_t ;
    00111 /*
    00112   Yes, all this really is needed to get all the various compilers to quit
    00113   complaining. We need the `(unsigned char)' to prevent some compilers from
    00114   complaining about the initialiser being out of range. Goes to the ANSI C
    00115   rule that `Character constants not preceded by the letter L have type int.'
    00116 */
    00117 #ifdef WORDS_BIGENDIAN
    00118     static fpunion_t QNaNbits UNUSED = { { (unsigned char) '\177',
    00119                                         (unsigned char) '\377',
    00120                                         (unsigned char) '\377',
    00121                                         (unsigned char) '\377',
    00122                                         (unsigned char) '\377',
    00123                                         (unsigned char) '\377',
    00124                                         (unsigned char) '\377',
    00125                                         (unsigned char) '\376' } } ;
    00126     static fpunion_t SNaNbits UNUSED = { { (unsigned char) '\177',
    00127                                         (unsigned char) '\360',
    00128                                         (unsigned char) '\0',
    00129                                         (unsigned char) '\0',
    00130                                         (unsigned char) '\0',
    00131                                         (unsigned char) '\0',
    00132                                         (unsigned char) '\0',
    00133                                         (unsigned char) '\001' } } ;
    00134     static fpunion_t Infbits UNUSED = { { (unsigned char) '\177',
    00135                                        (unsigned char) '\360',
    00136                                        (unsigned char) '\0',
    00137                                        (unsigned char) '\0',
    00138                                        (unsigned char) '\0',
    00139                                        (unsigned char) '\0',
    00140                                        (unsigned char) '\0',
    00141                                        (unsigned char) '\0' } } ;
    00142 #else
    00143     static fpunion_t QNaNbits UNUSED = { { (unsigned char) '\376',
    00144                                         (unsigned char) '\377',
    00145                                         (unsigned char) '\377',
    00146                                         (unsigned char) '\377',
    00147                                        (unsigned char) '\377',
    00148                                         (unsigned char) '\377',
    00149                                         (unsigned char) '\377',
    00150                                         (unsigned char) '\177' } } ;
    00151     static fpunion_t SNaNbits UNUSED = { { (unsigned char) '\001',
    00152                                         (unsigned char) '\0',
    00153                                         (unsigned char) '\0',
    00154                                         (unsigned char) '\0',
    00155                                         (unsigned char) '\0',
    00156                                         (unsigned char) '\0',
    00157                                         (unsigned char) '\360',
    00158                                         (unsigned char) '\177' } } ;
    00159     static fpunion_t Infbits UNUSED = { { (unsigned char) '\0',
    00160                                        (unsigned char) '\0',
    00161                                        (unsigned char) '\0',
    00162                                        (unsigned char) '\0',
    00163                                        (unsigned char) '\0',
    00164                                        (unsigned char) '\0',
    00165                                        (unsigned char) '\360',
    00166                                        (unsigned char) '\177' } } ;
    00167 #endif /* WORDS_BIGENDIAN */
    00168
    00169 /*
    00170   If we didn't find a quiet_nan function, fake it with a macro.
    00171 */
    00172
    00173 #ifndef DYLP_HAS_QUIET_NAN
    00174 # define quiet_nan(zz_dummy_zz) (QNaNbits.fpdbl)
    00175 #endif
    00176
    00177 /*
    00178   On some machines, HUGE_VAL isn't actually IEEE infinity. Make sure that
    00179   it really is IEEE infinity.
    00180 */
    00181
    00182 #undef HUGE_VAL
    00183 #define HUGE_VAL (Infbits.fpdbl)
    00184
    00185 /*
    00186   In a Sun/Solaris environment, the definitions and functions that support
    00187   IEEE floating point are in ieeefp.h. This seems to be true even if GNU
    00188   compilers are being used instead of Sun Workshop compilers. In a GNU/Linux
    00189   environment, the necessary definitions seem to live in math.h. The upshot
    00190   is that we need to explicitly pull in ieeefp.h here for a Sun environment.
    00191
    00192   In a Microsoft environment the correct functions look to be _finite and
    00193   _isnan from float.h.
    00194
    00195   Assign the proper names to finite and isnan, based on the values deduced by
    00196   configure. Again, check config_dylp to see the actual names. If either name
    00197   is already defined, bet that it's the correct definition.
    00198 */
    00199
    00200 #ifndef finite
    00201 # define finite DYLP_ISFINITE
    00202 #endif
    00203 #ifndef isnan
    00204 # define isnan  DYLP_ISNAN
    00205 #endif
    00206
    00207 #endif
    00208
    00209 /*
    00210   Packed Vectors
    00211
    00212   The packed vector type consists of a header plus an array of <index, value>
    00213   pairs for the non-default entries of the vector.
    00214
    00215   pkcoeff_struct
    00216
    00217   Field         Description
    00218   -----         -----------
    00219   ndx           the column/row index for the coefficient
    00220   val           the value of the coefficient
    00221
    00222   pkvec_struct
    00223
    00224   Field         Description
    00225   -----         -----------
    00226   ndx           the common index for all coefficients when the vector is a
    00227                 row or column from a matrix
    00228   nme           name associated with this vector, if any
    00229   dim           length of the vector when unpacked
    00230   dflt          the default value of coefficients not in coeffs
    00231   cnt           number of non-default coefficients in the coeffs array
    00232   sze           allocated capacity (in pkcoeff_struct's) of the coeffs array
    00233   coeffs        the array of (column/row index, coefficient) pairs
    00234
    00235   NOTE: pkvec_struct->coeffs is indexed from 0 and sized accordingly.
    00236 */
    00237
    00238 typedef struct { int ndx ;
    00239                    double val ; } pkcoeff_struct ;
    00240
    00241 typedef struct { int ndx ;
    00242                    const char *nme ;
    00243                    int dim ;
    00244                    double dflt ;
    00245                    int cnt ;
    00246                    int sze ;
    00247                    pkcoeff_struct *coeffs ; } pkvec_struct ;
    00248
    00249 pkvec_struct *pkvec_new(int sze) ;
    00250 bool pkvec_resize(pkvec_struct *pkvec, int sze) ;
    00251 void pkvec_free(pkvec_struct *pkvec) ;
    00252
    00253 bool pkvec_check(pkvec_struct *pkvec, const char *caller) ;
    00254
    00255 double pkvec_2norm(pkvec_struct *vec) ;
    00256
    00257 double exvec_1norm(double *vec, int len),
    00258        exvec_ssq(double *vec, int len),
    00259        exvec_2norm(double *vec, int len),
    00260        exvec_infnorm(double *vec, int len, int *p_jmax) ;
    00261
    00262 double pkvec_dotexvec(pkvec_struct *pkvec, double *exvec) ;
    00263
    00264 #endif /* _DYLP_VECTOR_H */

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines