memory.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2006 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <inttypes.h>
00021 
00022 #include <archon/util/memory.H>
00023 
00024 
00025 namespace Archon
00026 {
00027   namespace Utilities
00028   {
00029     vector<bool> detectNativeEndianness()
00030     {
00031       uintmax_t v = 1;
00032       char *p = reinterpret_cast<char *>(&v);
00033       // The bit pattern of the index of the non-zero byte describes the
00034       // native endianness in exactly the way described above.
00035       int i;
00036       for(i=0; i<static_cast<int>(sizeof(v)); ++i) if(p[i]) break;
00037 
00038       vector<bool> r;
00039       // Determine the number of bits in the endianness descriptor
00040       int n = 0;
00041       int w = sizeof(v) >> 1;
00042       while(w)
00043       {
00044         r.push_back(i&w);
00045         w >>= 1;
00046         ++n;
00047       }
00048       reverse(r.begin(), r.end());
00049       return r;
00050     }
00051 
00052 
00053     bool compareEndianness(const vector<bool> &a, const vector<bool> &b,
00054                            int levels)
00055     {
00056       vector<bool> c;
00057       if(b.empty())
00058       {
00059         if(a.empty()) return true;
00060         c = detectNativeEndianness();
00061       }
00062       else c = b;
00063 
00064       if(!levels) levels = max(a.size(), c.size());
00065 
00066       for(int i=0; i<levels; ++i)
00067         if(a[i < static_cast<int>(a.size()) ? i : a.size()-1] !=
00068            c[i < static_cast<int>(c.size()) ? i : c.size()-1]) return false;
00069 
00070       return true;
00071     }
00072 
00073 
00074     vector<int> computeBytePermutation(const vector<bool> &endianness,
00075                                        int levels)
00076     {
00077       vector<bool> native = detectNativeEndianness();
00078 
00079       // Construct identity map
00080       int n = 1<<levels;
00081       vector<int> permutation(n);
00082       for(int i=0; i<n; ++i) permutation[i] = i;
00083       
00084       // For each level
00085       for(int i=0; i<levels; ++i)
00086       {
00087         // Swap only if we hav endianness disagreement on this level
00088         if(native[i < static_cast<int>(native.size()) ? i : native.size()-1] ==
00089            endianness[i < static_cast<int>(endianness.size()) ? i :
00090                       endianness.size()-1]) continue;
00091 
00092         int swapBlockSize = 1 << i+1;
00093         int numberOfSwapBlocks = n / swapBlockSize;
00094         int numberOfSwapsPerBlock = swapBlockSize / 2;
00095 
00096         // For each block that needs to be swapped
00097         for(int j=0; j<numberOfSwapBlocks; ++j)
00098         {
00099           // For each swap
00100           for(int k=0; k<numberOfSwapsPerBlock; ++k)
00101           {
00102             int offset = j * swapBlockSize + k;
00103             swap(permutation[offset],
00104                  permutation[offset+numberOfSwapsPerBlock]);
00105           }
00106         }
00107       }
00108 
00109       return permutation;
00110     }
00111   }
00112 }

Generated on Sun Jul 30 22:55:44 2006 for Archon by  doxygen 1.4.4