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