oct-mem.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2009-2012 VZLU Prague
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 #if !defined (octave_memory_h)
00024 #define octave_memory_h 1
00025 
00026 #include <cstddef>
00027 #include <cstring>
00028 #include <algorithm>
00029 
00030 #include "oct-cmplx.h"
00031 #include "oct-inttypes.h"
00032 
00033 // NOTE: These functions are used to optimize stuff where performance is a
00034 // priority. They assume that the std::complex and octave_int can be
00035 // manipulated as plain memory, an assumption that is always true in practice
00036 // but not theoretically guaranteed by the C++ standard. In the future, C++ may
00037 // provide a better way to accomplish these tasks.
00038 
00039 inline size_t safe_size_comp (size_t n, size_t size)
00040 {
00041   if (n > static_cast<size_t> (-1) / size)
00042     throw std::bad_alloc ();
00043   return n * size;
00044 }
00045 
00046 // Unaliased copy. This boils down to memcpy, even for octave_int and complex types.
00047 
00048 template <class T>
00049 inline void copy_or_memcpy (size_t n, const T *src, T *dest)
00050 { std::copy (src, src + n, dest); }
00051 
00052 #define DEFINE_POD_UCOPY(T) \
00053 inline void copy_or_memcpy (size_t n, const T *src, T *dest) \
00054 { std::memcpy (dest, src, n * sizeof (T)); }
00055 
00056 DEFINE_POD_UCOPY (double)
00057 DEFINE_POD_UCOPY (float)
00058 DEFINE_POD_UCOPY (char)
00059 DEFINE_POD_UCOPY (short)
00060 DEFINE_POD_UCOPY (int)
00061 DEFINE_POD_UCOPY (long)
00062 DEFINE_POD_UCOPY (unsigned char)
00063 DEFINE_POD_UCOPY (unsigned short)
00064 DEFINE_POD_UCOPY (unsigned int)
00065 DEFINE_POD_UCOPY (unsigned long)
00066 
00067 DEFINE_POD_UCOPY (Complex)
00068 DEFINE_POD_UCOPY (FloatComplex)
00069 
00070 template <class T>
00071 DEFINE_POD_UCOPY (octave_int<T>)
00072 
00073 // Fill by value, with a check for zero. This boils down to memset if value is
00074 // a POD zero.
00075 template <class T>
00076 inline void fill_or_memset (size_t n, const T& value, T *dest)
00077 { std::fill_n (dest, n, value); }
00078 
00079 template <class T>
00080 inline bool helper_is_zero_mem (const T& value)
00081 {
00082   typedef typename query_integer_type<sizeof (T), false>::type IT; // get integer type of the same size.
00083   return *(reinterpret_cast<const IT *>(&value)) == 0;
00084 }
00085 
00086 template <class T>
00087 inline bool helper_is_zero_mem (const std::complex<T>& value)
00088 {
00089   return (helper_is_zero_mem (value.real ())
00090           && helper_is_zero_mem (value.imag ()));
00091 }
00092 
00093 template <class T>
00094 inline bool helper_is_zero_mem (const octave_int<T>& value)
00095 { return value.value () == T(); }
00096 
00097 #define DEFINE_POD_FILL(T) \
00098 inline void fill_or_memset (size_t n, const T& value, T *dest) \
00099 { \
00100   if (helper_is_zero_mem (value)) \
00101     std::memset (dest, 0, n * sizeof (T)); \
00102   else \
00103     std::fill_n (dest, n, value); \
00104 }
00105 
00106 DEFINE_POD_FILL (double)
00107 DEFINE_POD_FILL (float)
00108 DEFINE_POD_FILL (char)
00109 DEFINE_POD_FILL (short)
00110 DEFINE_POD_FILL (int)
00111 DEFINE_POD_FILL (long)
00112 DEFINE_POD_FILL (unsigned char)
00113 DEFINE_POD_FILL (unsigned short)
00114 DEFINE_POD_FILL (unsigned int)
00115 DEFINE_POD_FILL (unsigned long)
00116 
00117 DEFINE_POD_FILL (Complex)
00118 DEFINE_POD_FILL (FloatComplex)
00119 
00120 template <class T>
00121 DEFINE_POD_FILL (octave_int<T>)
00122 
00123 // Uninitialized allocation. Will not initialize memory for complex and octave_int.
00124 // Memory allocated by octave_new should be freed by octave_delete.
00125 template <class T>
00126 inline T *no_ctor_new (size_t n)
00127 {
00128   // Some systems let us allocate > 2GB memory even though size_t, which is either
00129   // buggy or completely cuckoo, so let's check here to stay safe.
00130   safe_size_comp (n, sizeof (T));
00131   return new T[n];
00132 }
00133 template <class T>
00134 inline void no_ctor_delete (T *ptr)
00135 { delete [] ptr; }
00136 
00137 #define DEFINE_POD_NEW_DELETE(T) \
00138 template <> \
00139 inline T *no_ctor_new<T > (size_t n) \
00140 { return reinterpret_cast<T *> (new char[safe_size_comp (n, sizeof (T))]); } \
00141 template <> \
00142 inline void no_ctor_delete<T > (T *ptr) \
00143 { delete [] reinterpret_cast<char *> (ptr); }
00144 
00145 DEFINE_POD_NEW_DELETE (Complex)
00146 DEFINE_POD_NEW_DELETE (FloatComplex)
00147 
00148 DEFINE_POD_NEW_DELETE (octave_int8)
00149 DEFINE_POD_NEW_DELETE (octave_int16)
00150 DEFINE_POD_NEW_DELETE (octave_int32)
00151 DEFINE_POD_NEW_DELETE (octave_int64)
00152 DEFINE_POD_NEW_DELETE (octave_uint8)
00153 DEFINE_POD_NEW_DELETE (octave_uint16)
00154 DEFINE_POD_NEW_DELETE (octave_uint32)
00155 DEFINE_POD_NEW_DELETE (octave_uint64)
00156 
00157 #endif /* octave_memory_h */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines