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 */