DyLP  trunk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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$
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 Files Functions Variables Typedefs Enumerations Enumerator Friends Defines