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