mach-info.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "f77-fcn.h"
00028 #include "lo-error.h"
00029 #include "mach-info.h"
00030 #include "singleton-cleanup.h"
00031 
00032 extern "C"
00033 {
00034   double F77_FUNC (d1mach, D1MACH) (const octave_idx_type&);
00035 }
00036 
00037 oct_mach_info *oct_mach_info::instance = 0;
00038 
00039 union equiv
00040 {
00041   double d;
00042   int i[2];
00043 };
00044 
00045 struct
00046 float_params
00047 {
00048   oct_mach_info::float_format fp_fmt;
00049   equiv fp_par[4];
00050 };
00051 
00052 #define INIT_FLT_PAR(fp, fmt, sm1, sm2, lrg1, lrg2, rt1, rt2, dv1, dv2) \
00053   do \
00054     { \
00055       fp.fp_fmt = (fmt); \
00056       fp.fp_par[0].i[0] = (sm1);  fp.fp_par[0].i[1] = (sm2); \
00057       fp.fp_par[1].i[0] = (lrg1); fp.fp_par[1].i[1] = (lrg2); \
00058       fp.fp_par[2].i[0] = (rt1);  fp.fp_par[2].i[1] = (rt2); \
00059       fp.fp_par[3].i[0] = (dv1);  fp.fp_par[3].i[1] = (dv2); \
00060     } \
00061   while (0)
00062 
00063 static int
00064 equiv_compare (const equiv *std, const equiv *v, int len)
00065 {
00066   int i;
00067   for (i = 0; i < len; i++)
00068     if (v[i].i[0] != std[i].i[0] || v[i].i[1] != std[i].i[1])
00069       return 0;
00070   return 1;
00071 }
00072 
00073 static oct_mach_info::float_format
00074 get_float_format (void)
00075 {
00076   oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown;
00077 
00078 #if defined (CRAY)
00079 
00080   // FIXME -- this should be determined automatically.
00081 
00082   native_float_fmt = oct_mach_info::flt_fmt_cray;
00083 
00084 #else
00085 
00086   float_params fp[5];
00087 
00088   INIT_FLT_PAR (fp[0], oct_mach_info::flt_fmt_ieee_big_endian,
00089                    1048576,  0,
00090                 2146435071, -1,
00091                 1017118720,  0,
00092                 1018167296,  0);
00093 
00094   INIT_FLT_PAR (fp[1], oct_mach_info::flt_fmt_ieee_little_endian,
00095                  0,    1048576,
00096                 -1, 2146435071,
00097                  0, 1017118720,
00098                  0, 1018167296);
00099 
00100   INIT_FLT_PAR (fp[2], oct_mach_info::flt_fmt_vax_d,
00101                    128,  0,
00102                 -32769, -1,
00103                   9344,  0,
00104                   9344,  0);
00105 
00106   INIT_FLT_PAR (fp[3], oct_mach_info::flt_fmt_vax_g,
00107                     16,  0,
00108                 -32769, -1,
00109                  15552,  0,
00110                  15552,  0);
00111 
00112   INIT_FLT_PAR (fp[4], oct_mach_info::flt_fmt_unknown,
00113                 0, 0,
00114                 0, 0,
00115                 0, 0,
00116                 0, 0);
00117 
00118   equiv mach_fp_par[4];
00119 
00120   mach_fp_par[0].d = F77_FUNC (d1mach, D1MACH) (1);
00121   mach_fp_par[1].d = F77_FUNC (d1mach, D1MACH) (2);
00122   mach_fp_par[2].d = F77_FUNC (d1mach, D1MACH) (3);
00123   mach_fp_par[3].d = F77_FUNC (d1mach, D1MACH) (4);
00124 
00125   int i = 0;
00126   do
00127     {
00128       if (equiv_compare (fp[i].fp_par, mach_fp_par, 4))
00129         {
00130           retval = fp[i].fp_fmt;
00131           break;
00132         }
00133     }
00134   while (fp[++i].fp_fmt != oct_mach_info::flt_fmt_unknown);
00135 
00136 #endif
00137 
00138   return retval;
00139 }
00140 
00141 static bool
00142 ten_little_endians (void)
00143 {
00144   // Are we little or big endian?  From Harbison & Steele.
00145 
00146   union
00147   {
00148     long l;
00149     char c[sizeof (long)];
00150   } u;
00151 
00152   u.l = 1;
00153 
00154   return (u.c[sizeof (long) - 1] == 1);
00155 }
00156 
00157 oct_mach_info::oct_mach_info (void)
00158   : native_float_fmt (get_float_format ()),
00159     big_chief (ten_little_endians ()) { }
00160 
00161 bool
00162 oct_mach_info::instance_ok (void)
00163 {
00164   bool retval = true;
00165 
00166   if (! instance)
00167     {
00168       instance = new oct_mach_info ();
00169 
00170       if (instance)
00171         singleton_cleanup_list::add (cleanup_instance);
00172     }
00173 
00174   if (! instance)
00175     {
00176       (*current_liboctave_error_handler)
00177         ("unable to create command history object!");
00178 
00179       retval = false;
00180     }
00181 
00182   return retval;
00183 }
00184 
00185 oct_mach_info::float_format
00186 oct_mach_info::native_float_format (void)
00187 {
00188   return (instance_ok ())
00189     ? instance->native_float_fmt : oct_mach_info::flt_fmt_unknown;
00190 }
00191 
00192 bool
00193 oct_mach_info::words_big_endian (void)
00194 {
00195   return (instance_ok ())
00196     ? instance->big_chief : false;
00197 }
00198 
00199 bool
00200 oct_mach_info::words_little_endian (void)
00201 {
00202   return (instance_ok ())
00203     ? (! instance->big_chief) : false;
00204 }
00205 
00206 oct_mach_info::float_format
00207 oct_mach_info::string_to_float_format (const std::string& s)
00208 {
00209   oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown;
00210 
00211   if (s == "native" || s == "n")
00212     retval = oct_mach_info::native_float_format ();
00213   else if (s == "ieee-be" || s == "b")
00214     retval = oct_mach_info::flt_fmt_ieee_big_endian;
00215   else if (s == "ieee-le" || s == "l")
00216     retval = oct_mach_info::flt_fmt_ieee_little_endian;
00217   else if (s == "vaxd" || s == "d")
00218     retval = oct_mach_info::flt_fmt_vax_d;
00219   else if (s == "vaxg" || s == "g")
00220     retval = oct_mach_info::flt_fmt_vax_g;
00221   else if (s == "cray" || s == "c")
00222     retval = oct_mach_info::flt_fmt_cray;
00223   else if (s == "unknown")
00224     retval = oct_mach_info::flt_fmt_unknown;
00225   else
00226     (*current_liboctave_error_handler)
00227       ("invalid architecture type specified");
00228 
00229   return retval;
00230 }
00231 
00232 std::string
00233 oct_mach_info::float_format_as_string (float_format flt_fmt)
00234 {
00235   std::string retval = "unknown";
00236 
00237   switch (flt_fmt)
00238     {
00239     case flt_fmt_ieee_big_endian:
00240       retval = "ieee_big_endian";
00241       break;
00242 
00243     case flt_fmt_ieee_little_endian:
00244       retval = "ieee_little_endian";
00245       break;
00246 
00247     case flt_fmt_vax_d:
00248       retval = "vax_d_float";
00249       break;
00250 
00251     case flt_fmt_vax_g:
00252       retval = "vax_g_float";
00253       break;
00254 
00255     case flt_fmt_cray:
00256       retval = "cray";
00257       break;
00258 
00259     default:
00260       break;
00261     }
00262 
00263   return retval;
00264 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines