//# Conversion.cc: A class with static functions to convert canonical format //# Copyright (C) 1996,2011 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #include #include #include #include #include #ifdef __SSE2__ #include #endif #ifdef _OPENMP #include #endif namespace casacore { //# NAMESPACE CASACORE - BEGIN size_t Conversion::boolToBit (void* to, const void* from, size_t nvalues) { const Bool* data = (const Bool*)from; unsigned char* bits = (unsigned char*)to; size_t i = 0; #ifdef __SSE2__ __m128i zero = _mm_setzero_si128(); for (i = 0; i < nvalues - (nvalues & 0xF); i+=16) { __m128i v = _mm_loadu_si128((const __m128i*)&data[i]); /* compare to zero to convert false -> 0xFF and true -> 0x00 */ v = _mm_cmpeq_epi8(v, zero); /* extract most significant bit of each byte * not result to revert compare against zero */ unsigned int r = ~(unsigned int)_mm_movemask_epi8(v); /* store the 16 bits */ memcpy(&bits[i / 8], &r, 2); } data = &data[i]; #endif //# Fill as many full bytes as possible. //# Note: the compiler can optimize much better for j<8 than j 0) { unsigned char& ch = bits[nfbytes]; ch = 0; //# Take care of correct number of bits in last byte. for (size_t j=0; j 0 || endBit1 < 8) { unsigned char& ch = bits[startByte++]; unsigned char mask = (1 << startBit1); for (size_t j=startBit1; j 0) { unsigned char& ch = bits[endByte]; unsigned char mask = 1; for (size_t j=0; j 0) { int ch = bits[nfbytes]; for (size_t j=0; j= 32 * 1024) num_threads(nthr) #endif for (size_t i = 0; i < nwords; ++i) { data[i] = conv_tab[bits[i]].d; } return nwords * (bits_per_loop / 8) + bitToBool_ (&data[nwords], &bits[nwords], nvalues - (nwords * bits_per_loop)); } void Conversion::bitToBool (void* to, const void* from, size_t startBit, size_t nvalues) { Bool* data = (Bool*)to; const unsigned char* bits = (const unsigned char*)from; //# Determine the first and last byte to be read //# and the first and last bit in the first and last byte. size_t startByte = startBit / 8; size_t startBit1 = startBit - 8 * startByte; size_t endByte = (startBit + nvalues) / 8; size_t endBit1 = 8; size_t endBit2 = startBit + nvalues - 8 * endByte; //# Take care if only one byte has to be handled. if (startByte == endByte) { endBit1 = endBit2; endBit2 = 0; } //# Set the bits in the first byte (if needed). if (startBit1 > 0 || endBit1 < 8) { int ch = bits[startByte++]; for (size_t j=startBit1; j 0) { int ch = bits[endByte]; for (size_t j=0; j