code:
/*
qra64.c
Encoding/decoding functions for the QRA64 mode

(c) 2016 - Nico Palermo, IV3NWV

-------------------------------------------------------------------------------

   qracodes is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   qracodes 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with qracodes source distribution.
   If not, see <http://www.gnu.org/licenses/>.

-----------------------------------------------------------------------------

QRA code used in this sowftware release:

QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in
qra13_64_64_irr_e.h /.c)

Codes with K=13 are designed to include a CRC as the 13th information symbol
and improve the code UER (Undetected Error Rate).
The CRC symbol is not sent along the channel (the codes are punctured) and the
resulting code is a (12,63) code
*/
//----------------------------------------------------------------------------

#include <stdlib.h>
#include <string.h>

#include "qra64.h"
#include "../qracodes/qracodes.h"
#include "../qracodes/qra13_64_64_irr_e.h"
#include "../qracodes/pdmath.h"
#include "../qracodes/normrnd.h"

// Code parameters of the QRA64 mode
#define QRA64_CODE  qra_13_64_64_irr_e
#define QRA64_NMSG  218        // Must much value indicated in QRA64_CODE.NMSG

#define QRA64_KC (QRA64_K+1)   // Information symbols (crc included)
#define QRA64_NC (QRA64_N+1)   // Codeword length (as defined in the code)
#define QRA64_NITER 100	       // max number of iterations per decode

// static functions declarations ----------------------------------------------
static int  calc_crc6(const int *x, int sz);
static void ix_mask(float *dst, const float *src, const int *mask,
		    const int *x);
static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix);
static int qra64_do_decode(int *x, const float *pix, const int *ap_mask,
			    const int *ap_x);
static float qra64_fastfading_estim_noise_std(
				float *rxen,
				const float esnometric,
				const int submode);
static void qra64_fastfading_intrinsics(
				float *pix,
				const float *rxamp,
				const float *hptr,
				const int    hlen,
				const float cmetric,
				const int submode);
static float qra64_fastfading_msg_esno(
			const int *ydec,
			const float *rxamp,
			const float sigma,
			const float EsNoMetric,
			const int hlen,
			const int submode);

// a-priori information masks for fields in JT65-like msgs --------------------
#define MASK_CQQRZ      0xFFFFFFC // CQ/QRZ calls common bits
#define MASK_CALL1      0xFFFFFFF
#define MASK_CALL2      0xFFFFFFF
#define MASK_GRIDFULL	0xFFFF
#define MASK_GRIDFULL12	0x3FFC	  // less aggressive mask (to be used with full AP decoding)
#define MASK_GRIDBIT	0x8000	  // b[15] is 1 for free text, 0 otherwise
// ----------------------------------------------------------------------------

qra64codec *qra64_init(int flags)
{

  // Eb/No value for which we optimize the decoder metric
  const float EbNodBMetric = 2.8f;
  const float EbNoMetric   = (float)pow(10,EbNodBMetric/10);
  const float R = 1.0f*(QRA64_KC)/(QRA64_NC);

  qra64codec *pcodec = (qra64codec*)malloc(sizeof(qra64codec));

  if (!pcodec)
    return 0;	// can't allocate memory

  pcodec->decEsNoMetric   = 1.0f*QRA64_m*R*EbNoMetric;
  pcodec->apflags			= flags;

  memset(pcodec->apmsg_set,0,APTYPE_SIZE*sizeof(int));

  if (flags==QRA_NOAP)
    return pcodec;

  // for QRA_USERAP and QRA_AUTOAP modes we always enable [CQ/QRZ ? ?] mgs look-up.
  // encode CQ/QRZ AP messages
  // NOTE: Here we handle only CQ and QRZ msgs.
  // 'CQ nnn', 'CQ DX' and 'DE' msgs will be handled by the decoder
  // as messages with no a-priori knowledge
  qra64_apset(pcodec, CALL_CQ, 0, GRID_BLANK, APTYPE_CQQRZ);

  // initialize masks for decoding with a-priori information
  encodemsg_jt65(pcodec->apmask_cqqrz,     MASK_CQQRZ, 0, MASK_GRIDBIT);
  encodemsg_jt65(pcodec->apmask_cqqrz_ooo, MASK_CQQRZ, 0, MASK_GRIDFULL);
  encodemsg_jt65(pcodec->apmask_call1,     MASK_CALL1, 0, MASK_GRIDBIT);
  encodemsg_jt65(pcodec->apmask_call1_ooo, MASK_CALL1, 0, MASK_GRIDFULL);
  encodemsg_jt65(pcodec->apmask_call2,     0, MASK_CALL2, MASK_GRIDBIT);
  encodemsg_jt65(pcodec->apmask_call2_ooo, 0, MASK_CALL2, MASK_GRIDFULL);
  encodemsg_jt65(pcodec->apmask_call1_call2,     MASK_CALL1,MASK_CALL2, MASK_GRIDBIT);
  encodemsg_jt65(pcodec->apmask_call1_call2_grid,MASK_CALL1,MASK_CALL2, MASK_GRIDFULL12);
  encodemsg_jt65(pcodec->apmask_cq_call2,     MASK_CQQRZ, MASK_CALL2, MASK_GRIDBIT);
  encodemsg_jt65(pcodec->apmask_cq_call2_ooo, MASK_CQQRZ, MASK_CALL2, MASK_GRIDFULL12);

  return pcodec;
}

void qra64_close(qra64codec *pcodec)
{
	free(pcodec);
}

int qra64_apset(qra64codec *pcodec, const int mycall, const int hiscall, const int grid, const int aptype)
{
// Set decoder a-priori knowledge accordingly to the type of the message to look up for
// arguments:
//		pcodec    = pointer to a qra64codec data structure as returned by qra64_init
//		mycall    = mycall to look for
//		hiscall   = hiscall to look for
//		grid      = grid to look for
//		aptype    = define and masks the type of AP to be set accordingly to the following:
//			APTYPE_CQQRZ     set [cq/qrz ?       ?/blank]
//			APTYPE_MYCALL    set [mycall ?       ?/blank]
//			APTYPE_HISCALL   set [?      hiscall ?/blank]
//			APTYPE_BOTHCALLS set [mycall hiscall ?]
//			APTYPE_FULL		 set [mycall hiscall grid]
//			APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank] and [cq/qrz hiscall grid]
// returns:
//		0   on success
//      -1  when qra64_init was called with the QRA_NOAP flag
//		-2  invalid apytpe

	if (pcodec->apflags==QRA_NOAP)
		return -1;

	switch (aptype) {
		case APTYPE_CQQRZ:
			encodemsg_jt65(pcodec->apmsg_cqqrz,  CALL_CQ, 0, GRID_BLANK);
			break;
		case APTYPE_MYCALL:
			encodemsg_jt65(pcodec->apmsg_call1,  mycall,  0, GRID_BLANK);
			break;
		case APTYPE_HISCALL:
			encodemsg_jt65(pcodec->apmsg_call2,  0, hiscall, GRID_BLANK);
			break;
		case APTYPE_BOTHCALLS:
			encodemsg_jt65(pcodec->apmsg_call1_call2,  mycall, hiscall, GRID_BLANK);
			break;
		case APTYPE_FULL:
			encodemsg_jt65(pcodec->apmsg_call1_call2_grid,  mycall, hiscall, grid);
			break;
		case APTYPE_CQHISCALL:
			encodemsg_jt65(pcodec->apmsg_cq_call2,      CALL_CQ, hiscall, GRID_BLANK);
			encodemsg_jt65(pcodec->apmsg_cq_call2_grid, CALL_CQ, hiscall, grid);
			break;
		default:
			return -2;	// invalid ap type
		}

	  pcodec->apmsg_set[aptype]=1;	// signal the decoder to look-up for the specified type

	  return 0;
}
void qra64_apdisable(qra64codec *pcodec, const int aptype)
{
	if (pcodec->apflags==QRA_NOAP)
		return;

	if (aptype<APTYPE_CQQRZ || aptype>=APTYPE_SIZE)
		return;

	pcodec->apmsg_set[aptype] = 0;	//  signal the decoder not to look-up to the specified type
}

void qra64_encode(qra64codec *pcodec, int *y, const int *x)
{
  int encx[QRA64_KC];	// encoder input buffer
  int ency[QRA64_NC];	// encoder output buffer

  int hiscall,mycall,grid;

  memcpy(encx,x,QRA64_K*sizeof(int));		// Copy input to encoder buffer
  encx[QRA64_K]=calc_crc6(encx,QRA64_K);	// Compute and add crc symbol
  qra_encode(&QRA64_CODE, ency, encx);	 // encode msg+crc using given QRA code

  // copy codeword to output puncturing the crc symbol
  memcpy(y,ency,QRA64_K*sizeof(int));		// copy information symbols
  memcpy(y+QRA64_K,ency+QRA64_KC,QRA64_C*sizeof(int)); // copy parity symbols

  if (pcodec->apflags!=QRA_AUTOAP)
    return;

  // Here we handle the QRA_AUTOAP mode --------------------------------------------

  // When a [hiscall mycall ?] msg is detected we instruct the decoder
  // to look for [mycall hiscall ?] msgs
  // otherwise when a [cq mycall ?] msg is sent we reset the APTYPE_BOTHCALLS

  // look if the msg sent is a std type message (bit15 of grid field = 0)
  if ((x[9]&0x80)==1)
    return;	// no, it's a text message, nothing to do

  // It's a [hiscall mycall grid] message

  // We assume that mycall is our call (but we don't check it)
  // hiscall the station we are calling or a general call (CQ/QRZ/etc..)
  decodemsg_jt65(&hiscall,&mycall,&grid,x);

  if ((hiscall>=CALL_CQ && hiscall<=CALL_CQ999) || hiscall==CALL_CQDX ||
      hiscall==CALL_DE) {
	// tell the decoder to look for msgs directed to us
	qra64_apset(pcodec,mycall,0,0,APTYPE_MYCALL);
    // We are making a general call and don't know who might reply
    // Reset APTYPE_BOTHCALLS so decoder won't look for [mycall hiscall ?] msgs
    qra64_apdisable(pcodec,APTYPE_BOTHCALLS);
  } else {
    // We are replying to someone named hiscall
    // Set APTYPE_BOTHCALLS so decoder will try for [mycall hiscall ?] msgs
    qra64_apset(pcodec,mycall, hiscall, GRID_BLANK, APTYPE_BOTHCALLS);
  }

}

#define EBNO_MIN -10.0f		// minimum Eb/No value returned by the decoder (in dB)
int qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *rxen)
{
  int k;
  float *srctmp, *dsttmp;
  float ix[QRA64_NC*QRA64_M];		// (depunctured) intrisic information
  int   xdec[QRA64_KC];				// decoded message (with crc)
  int   ydec[QRA64_NC];				// re-encoded message (for snr calculations)
  float noisestd;					// estimated noise variance
  float msge;						// estimated message energy
  float ebnoval;					// estimated Eb/No
  int rc;

  if (QRA64_NMSG!=QRA64_CODE.NMSG)      // sanity check
    return -16;				// QRA64_NMSG define is wrong

  // compute symbols intrinsic probabilities from received energy observations
  noisestd = qra_mfskbesselmetric(ix, rxen, QRA64_m, QRA64_N,pcodec->decEsNoMetric);

  // de-puncture observations adding a uniform distribution for the crc symbol

  // move check symbols distributions one symbol towards the end
  dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1);	//Point to last symbol prob dist
  srctmp = dsttmp-QRA64_M;              // source is the previous pd
  for (k=0;k<QRA64_C;k++) {
    pd_init(dsttmp,srctmp,QRA64_M);
    dsttmp -=QRA64_M;
    srctmp -=QRA64_M;
  }
  // Initialize crc prob to a uniform distribution
  pd_init(dsttmp,pd_uniform(QRA64_m),QRA64_M);

  // Try to decode using all AP cases if required
  rc = qra64_decode_attempts(pcodec, xdec, ix);

  if (rc<0)
	  return rc;	// no success

  // successfull decode --------------------------------

  // copy decoded message (without crc) to output buffer
  memcpy(x,xdec,QRA64_K*sizeof(int));

  if (ebno==0)	// null pointer indicates we are not interested in the Eb/No estimate
	  return rc;

  // reencode message and estimate Eb/No
  qra_encode(&QRA64_CODE, ydec, xdec);
  // puncture crc
  memmove(ydec+QRA64_K,ydec+QRA64_KC,QRA64_C*sizeof(int));
  // compute total power of decoded message
  msge = 0;
  for (k=0;k<QRA64_N;k++) {
	  msge +=rxen[ydec[k]];	// add energy of current symbol
	  rxen+=QRA64_M;			// ptr to next symbol
	  }

  // NOTE:
  // To make a more accurate Eb/No estimation we should compute the noise variance
  // on all the rxen values but the transmitted symbols.
  // Noisestd is compute by qra_mfskbesselmetric assuming that
  // the signal power is much less than the total noise power in the QRA64_M tones
  // but this is true only if the Eb/No is low.
  // Here, in order to improve accuracy, we linearize the estimated Eb/No value empirically
  // (it gets compressed when it is very high as in this case the noise variance
  // is overestimated)

  // this would be the exact value if the noisestd were not overestimated at high Eb/No
  ebnoval = (0.5f/(QRA64_K*QRA64_m))*msge/(noisestd*noisestd)-1.0f;

  // Empirical linearization (to remove the noise variance overestimation)
  // the resulting SNR is accurate up to +20 dB (51 dB Eb/No)
  if (ebnoval>57.004f)
	  ebnoval=57.004f;
  ebnoval = ebnoval*57.03f/(57.03f-ebnoval);

  // compute value in dB
  if (ebnoval<=0)
	  ebnoval = EBNO_MIN; // assume a minimum, positive value
  else
	  ebnoval = 10.0f*(float)log10(ebnoval);
	  if (ebnoval<EBNO_MIN)
		  ebnoval = EBNO_MIN;

  *ebno = ebnoval;

  return rc;
}

// Tables of fading amplitudes coefficients for QRA64 (Ts=6912/12000)
// As the fading is assumed to be symmetric around the nominal frequency
// only the leftmost and the central coefficient are stored in the tables.
// (files have been generated with the Matlab code efgengauss.m and efgenlorentz.m)
#include "fadampgauss.c"
#include "fadamplorentz.c"

int qra64_decode_fastfading(
				qra64codec *pcodec,		// ptr to the codec structure
				float *ebno,			// ptr to where the estimated Eb/No value will be saved
				int *x,					// ptr to decoded message
				float *rxen,		    // ptr to received symbol energies array
				const int submode,		// submode idx (0=QRA64A ... 4=QRA64E)
				const float B90,	    // spread bandwidth (90% fractional energy)
				const int fadingModel)  // 0=Gaussian 1=Lorentzian fade model

// Decode a QRA64 msg using a fast-fading metric
//
// rxen: The array of the received bin energies
//       Bins must be spaced by integer multiples of the symbol rate (1/Ts Hz)
//       The array must be an array of total length U = L x N where:
//			L: is the number of frequency bins per message symbol (see after)
//          N: is the number of symbols in a QRA64 msg (63)

//       The number of bins/symbol L depends on the selected submode accordingly to
//		 the following rule:
//			L = (64+64*2^submode+64) = 64*(2+2^submode)
//		 Tone 0 is always supposed to be at offset 64 in the array.
//		 The m-th tone nominal frequency is located at offset 64 + m*2^submode (m=0..63)
//
//		 Submode A: (2^submode = 1)
//          L = 64*3 = 196 bins/symbol
//          Total length of the energies array: U = 192*63 = 12096 floats
//
//		 Submode B: (2^submode = 2)
//          L = 64*4 = 256 bins/symbol
//          Total length of the energies array: U = 256*63 = 16128 floats
//
//		 Submode C: (2^submode = 4)
//          L = 64*6 = 384 bins/symbol
//          Total length of the energies array: U = 384*63 = 24192 floats
//
//		 Submode D: (2^submode = 8)
//          L = 64*10 = 640 bins/symbol
//          Total length of the energies array: U = 640*63 = 40320 floats
//
//		 Submode E: (2^submode = 16)
//          L = 64*18 = 1152 bins/symbol
//          Total length of the energies array: U = 1152*63 = 72576 floats
//
//		Note: The rxen array is modified and reused for internal calculations.
//
//
//	B90: spread fading bandwidth in Hz (90% fractional average energy)
//
//			B90 should be in the range 1 Hz ... 238 Hz
//			The value passed to the call is rounded to the closest value among the
//			64 available values:
//				B = 1.09^k Hz, with k=0,1,...,63
//
//			I.e. B90=27 Hz will be approximated in this way:
//				k = rnd(log(27)/log(1.09)) = 38
//              B90 = 1.09^k = 1.09^38 = 26.4 Hz
//
//          For any input value the maximum rounding error is not larger than +/- 5%
//

{

  int k;
  float *srctmp, *dsttmp;
  float ix[QRA64_NC*QRA64_M];		// (depunctured) intrisic information
  int   xdec[QRA64_KC];				// decoded message (with crc)
  int   ydec[QRA64_NC];				// re-encoded message (for snr calculations)
  float noisestd;					// estimated noise std
  float esno,ebnoval;				// estimated Eb/No
  float tempf;
  float EsNoMetric, cmetric;
  int rc;
  int hidx, hlen;
  const float *hptr;

	if (QRA64_NMSG!=QRA64_CODE.NMSG)
		return -16;					// QRA64_NMSG define is wrong

	if (submode<0 || submode>4)
		return -17;				// invalid submode

	if (B90<1.0f || B90>238.0f)
		return -18;				// B90 out of range

	// compute index to most appropriate amplitude weighting function coefficients
    hidx = (int)(log((float)B90)/log(1.09f) - 0.499f);

	if (hidx<0 || hidx > 64)
		return -19;				// index of weighting function out of range

	if (fadingModel==0) {	 // gaussian fading model
		// point to gaussian weighting taps
		hlen = hlen_tab_gauss[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
		hptr = hptr_tab_gauss[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
		}
	else if (fadingModel==1) {
		// point to lorentzian weighting taps
		hlen = hlen_tab_lorentz[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
		hptr = hptr_tab_lorentz[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
		}
	else
		return -20;			// invalid fading model index

	// compute (euristically) the optimal decoder metric accordingly the given spread amount
	// We assume that the decoder threshold is:
	//		Es/No(dB) = Es/No(AWGN)(dB) + 8*log(B90)/log(240)(dB)
	// that's to say, at the maximum Doppler spread bandwidth (240 Hz) there's a ~8 dB Es/No degradation
	// over the AWGN case
	tempf = 8.0f*(float)log((float)B90)/(float)log(240.0f);
	EsNoMetric = pcodec->decEsNoMetric*(float)pow(10.0f,tempf/10.0f);

	// Step 1 -----------------------------------------------------------------------------------
	// Evaluate the noise stdev from the received energies at nominal tone frequencies
    // and transform energies to amplitudes
	tempf = hptr[hlen-1];				// amplitude weigth at nominal freq;
	tempf = tempf*tempf;				// fractional energy at nominal freq. bin

	noisestd = qra64_fastfading_estim_noise_std(rxen, EsNoMetric, submode);
	cmetric = (float)sqrt(M_PI_2*EsNoMetric)/noisestd;

	// Step 2 -----------------------------------------------------------------------------------
	// Compute message symbols probability distributions
	qra64_fastfading_intrinsics(ix, rxen, hptr, hlen, cmetric, submode);

	// Step 3 ---------------------------------------------------------------------------
	// De-puncture observations adding a uniform distribution for the crc symbol
	// Move check symbols distributions one symbol towards the end
	dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1);	//Point to last symbol prob dist
	srctmp = dsttmp-QRA64_M;              // source is the previous pd
	for (k=0;k<QRA64_C;k++) {
		pd_init(dsttmp,srctmp,QRA64_M);
		dsttmp -=QRA64_M;
		srctmp -=QRA64_M;
		}
	// Initialize crc prob to a uniform distribution
	pd_init(dsttmp,pd_uniform(QRA64_m),QRA64_M);

	// Step 4 ---------------------------------------------------------------------------
	// Attempt to decode
	rc = qra64_decode_attempts(pcodec, xdec, ix);
	if (rc<0)
	  return rc;	// no success

	// copy decoded message (without crc) to output buffer
	memcpy(x,xdec,QRA64_K*sizeof(int));

	// Step 5 ----------------------------------------------------------------------------
	// Estimate the message Eb/No

	if (ebno==0)	// null pointer indicates we are not interested in the Eb/No estimate
		return rc;

	// reencode message to estimate Eb/No
	qra_encode(&QRA64_CODE, ydec, xdec);
	// puncture crc
	memmove(ydec+QRA64_K,ydec+QRA64_KC,QRA64_C*sizeof(int));

	// compute Es/N0 of decoded message
	esno = qra64_fastfading_msg_esno(ydec,rxen,noisestd, EsNoMetric, hlen,submode);

	// as the weigthing function include about 90% of the energy
	// we could compute the unbiased esno with:
	// esno = esno/0.9;

	// this would be the exact value if the noisestd were not overestimated at high Eb/No
	ebnoval = 1.0f/(1.0f*QRA64_K/QRA64_N*QRA64_m)*esno;

	// compute value in dB
	if (ebnoval<=0)
	  ebnoval = EBNO_MIN; // assume a minimum, positive value
	else
	  ebnoval = 10.0f*(float)log10(ebnoval);
	  if (ebnoval<EBNO_MIN)
		  ebnoval = EBNO_MIN;

	*ebno = ebnoval;

  return rc;

}

int qra64_fastfading_channel(float **rxen, const int *xmsg, const int submode, const float EbN0dB, const float B90, const int fadingModel)
{
	// Simulate transmission over a fading channel and non coherent detection

	// Set rxen to point to an array of bin energies formatted as required
	// by the (fast-fading) decoding routine

	// returns 0 on success or negative values on error conditions

	static float *channel_out = NULL;
	static int    channel_submode = -1;

	int bpt = (1<<submode);			// bins per tone
	int bps = QRA64_M*(2+bpt);		// total number of bins per symbols
	int bpm = bps*QRA64_N;			// total number of bins in a message
	int n,j,hidx, hlen;
	const float *hptr;
	float *cursym,*curtone;

	float iq[2];
	float *curi, *curq;

//	float tote=0;	// debug

	float N0, EsN0, Es, A, sigmanoise, sigmasig;

	if (rxen==NULL)
		return -1;		// rxen must be a non-null ptr

	// allocate output buffer if not yet done or if submode changed
	if (channel_out==NULL || submode!=channel_submode) {

		// unallocate previous buffer
		if (channel_out)
			free(channel_out);

		// allocate new buffer
		// we allocate twice the mem so that we can store/compute complex amplitudes
		channel_out = (float*)malloc(bpm*sizeof(float)*2);
		if (channel_out==NULL)
			return -2;	// error allocating memory

		channel_submode = submode;
		}

	if (B90<1.0f || B90>238.0f)
		return -18;				// B90 out of range

	// compute index to most appropriate amplitude weighting function coefficients
    hidx = (int)(log((float)B90)/log(1.09f) - 0.499f);

	if (hidx<0 || hidx > 64)
		return -19;				// index of weighting function out of range

	if (fadingModel==0) {	 // gaussian fading model
		// point to gaussian weighting taps
		hlen = hlen_tab_gauss[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
		hptr = hptr_tab_gauss[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
		}
	else if (fadingModel==1) {
		// point to lorentzian weighting taps
		hlen = hlen_tab_lorentz[hidx];	 // hlen = (L+1)/2 (where L=(odd) number of taps of w fun)
		hptr = hptr_tab_lorentz[hidx];     // pointer to the first (L+1)/2 coefficients of w fun
		}
	else
		return -20;			// invalid fading model index

	// Compute the unfaded tone amplitudes from the Eb/No value passed to the call
	N0 = 1.0f;	// assume unitary noise PSD
	sigmanoise = (float)sqrt(N0/2);
	EsN0 = (float)pow(10.0f,EbN0dB/10.0f)*QRA64_m*QRA64_K/QRA64_N; // Es/No = m*R*Eb/No
	Es   = EsN0*N0;
	A    = (float)sqrt(Es/2.0f);	// unfaded tone amplitude (i^2+q^2 = Es/2+Es/2 = Es)

	// Generate gaussian noise iq components
	normrnd_s(channel_out, bpm*2, 0 , sigmanoise);

	// Add message symbols energies
	for (n=0;n<QRA64_N;n++) {

		cursym  = channel_out+n*bps + QRA64_M; // point to n-th symbol
		curtone = cursym+xmsg[n]*bpt;	 // point to encoded tone
		curi    = curtone-hlen+1;		 // point to real part of first bin
		curq    = curtone-hlen+1+bpm;	 // point to imag part of first bin

		// generate Rayleigh faded bins with given average energy and add to noise
		for (j=0;j<hlen;j++) {
			sigmasig = A*hptr[j];
			normrnd_s(iq, 2, 0 , sigmasig);
//			iq[0]=sigmasig*sqrt(2); iq[1]=0;	debug: used to verify Eb/No
			*curi++ += iq[0];
			*curq++ += iq[1];
//			tote +=iq[0]*iq[0]+iq[1]*iq[1];		// debug
			}
		for (j=hlen-2;j>=0;j--) {
			sigmasig = A*hptr[j];
			normrnd_s(iq, 2, 0 , sigmasig);
//			iq[0]=sigmasig*sqrt(2); iq[1]=0;	debug: used to verify Eb/No
			*curi++ += iq[0];
			*curq++ += iq[1];
//			tote +=iq[0]*iq[0]+iq[1]*iq[1];		// debug
			}

		}

//	tote = tote/QRA64_N;	// debug

	// compute total bin energies (S+N) and store in first half of buffer
	curi = channel_out;
	curq = channel_out+bpm;
	for (n=0;n<bpm;n++)
		channel_out[n] = curi[n]*curi[n] + curq[n]*curq[n];

	// set rxen to point to the channel output energies
	*rxen = channel_out;

	return 0;
}

// Static functions definitions ----------------------------------------------

// fast-fading static functions --------------------------------------------------------------

static float qra64_fastfading_estim_noise_std(float *rxen, const float esnometric, const int submode)
{
	// estimate the noise standard deviation from nominal frequency symbol bins
	// transform energies to amplitudes

	// rxen = message symbols energies (overwritten with symbols amplitudes)
	// esnometric = Es/No at nominal frequency bin for which we compute the decoder metric
	// submode = submode used (0=A...4=E)

	int bpt = (1<<submode);			// bins per tone
	int bps = QRA64_M*(2+bpt);		// total number of bins per symbols
	int bpm = bps*QRA64_N;			// total number of bins in a message
	int k;
	float sigmaest;

	// estimate noise std
	sigmaest = 0;
	for (k=0;k<bpm;k++) {
		sigmaest += rxen[k];
		// convert energies to amplitudes for later use
		rxen[k] = (float)sqrt(rxen[k]);	// we do it in place to avoid memory allocations
		}
	sigmaest = sigmaest/bpm;
	sigmaest = (float)sqrt(sigmaest/(1.0f+esnometric/bps)/2.0f);

	// Note: sigma is overestimated by the (unknown) factor sqrt((1+esno(true)/bps)/(1+esnometric/bps))

	return sigmaest;
}

static void qra64_fastfading_intrinsics(
				float *pix,
				const float *rxamp,
				const float *hptr,
				const int    hlen,
				const float cmetric,
				const int submode)
{

	// For each symbol in a message:
	// a) Compute tones loglikelihoods as a sum of products between of the expected
	// amplitude fading coefficient and received amplitudes.
	// Each product is computed as log(I0(hk*xk*cmetric)) where hk is the average fading amplitude,
	// xk is the received amplitude at bin offset k, and cmetric is a constant dependend on the
	// Eb/N0 value for which the metric is optimized
	// The function y = log(I0(x)) is approximated as y = x^2/(x+e)
	// b) Compute intrinsic symbols probability distributions from symbols loglikelihoods

	int n,k,j, bps, bpt;
	const float *cursym, *curbin;
	float *curix;
	float u, maxloglh, loglh, sumix;

	bpt = 1<<submode;				// bins per tone
	bps = QRA64_M*(2+bpt);			// bins per symbol

	for (n=0;n<QRA64_N;n++) {			// for each symbol in the message
		cursym = rxamp+n*bps + QRA64_M;	// point to current symbol nominal bin
		maxloglh = 0;
		curix  = pix+n*QRA64_M;
		for (k=0;k<QRA64_M;k++) {   // for each tone in the current symbol
			curbin = cursym + k*bpt -hlen+1;	// ptr to lowest bin of the current tone
			// compute tone loglikelihood as a weighted sum of bins loglikelihoods
			loglh = 0.f;
			for (j=0;j<hlen;j++) {
				u = *curbin++ * hptr[j]*cmetric;
				u = u*u/(u+(float)M_E);	// log(I0(u)) approx.
				loglh = loglh + u;
				}
			for (j=hlen-2;j>=0;j--) {
				u = *curbin++ * hptr[j]*cmetric;
				u = u*u/(u+(float)M_E);	// log(I0(u)) approx.
				loglh = loglh + u;
				}
			if (loglh>maxloglh)		// keep track of the max loglikelihood
				maxloglh = loglh;
			curix[k]=loglh;
			}
		// scale to likelihoods
		sumix = 0.f;
		for (k=0;k<QRA64_M;k++) {
			u = (float)exp(curix[k]-maxloglh);
			curix[k]=u;
			sumix +=u;
			}
		// scale to probabilities
		sumix = 1.0f/sumix;
		for (k=0;k<QRA64_M;k++)
			curix[k] = curix[k]*sumix;
		}
}

static float qra64_fastfading_msg_esno(
			const int *ydec,
			const float *rxamp,
			const float sigma,
			const float EsNoMetric,
			const int hlen,
			const int submode)
{
	// Estimate msg Es/N0

	int n,j, bps, bpt;
	const float *cursym, *curtone, *curbin;
	float u, msgsn,esno;
	int tothlen = 2*hlen-1;

	bpt = 1<<submode;				// bins per tone
	bps = QRA64_M*(2+bpt);			// bins per symbol

	msgsn = 0;
	for (n=0;n<QRA64_N;n++) {
		cursym  = rxamp+n*bps + QRA64_M; // point to n-th symbol amplitudes
		curtone = cursym+ydec[n]*bpt;	 // point to decoded tone amplitudes
		curbin  = curtone-hlen+1;		 // point to first bin amplitude

		// sum bin energies
		for (j=0;j<hlen;j++) {
			u = *curbin++;
			msgsn += u*u;
			}
		for (j=hlen-2;j>=0;j--) {
			u = *curbin++;
			msgsn += u*u;
			}

		}

	msgsn =  msgsn/(QRA64_N*tothlen);	// avg msg energy per bin (noise included)

	// as sigma is overestimated (sigmatrue = sigma*sqrt((1+EsNoMetric/bps)/(1+EsNo/bps))
	// we have: msgsn = (1+x/hlen)/(1+x/bps)*2*sigma^2*(1+EsnoMetric/bps), where x = Es/N0(true)
	//
	// we can then write:
	// u = msgsn/2.0f/(sigma*sigma)/(1.0f+EsNoMetric/bps);
	// (1+x/hlen)/(1+x/bps) = u

	u = msgsn/(2.0f*sigma*sigma)/(1.0f+EsNoMetric/bps);

	// check u>1
	if (u<1)
		return 0.f;

	// check u<bps/tot hlen
	if (u>(bps/tothlen))
		return 10000.f;

	// solve for Es/No
	esno = (u-1.0f)/(1.0f/tothlen-u/bps);

	return esno;

}

// Attempt to decode given intrisic information
static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix)
{
  int rc;

  // Attempt to decode without a-priori info --------------------------------
  rc = qra64_do_decode(xdec, ix, NULL, NULL);
  if (rc>=0)
	  return 0; // successfull decode with AP0
  else
	  if (pcodec->apflags==QRA_NOAP)
		  // nothing more to do
		  return rc; // rc<0 = unsuccessful decode

  // Here we handle decoding with AP knowledge

  // Attempt to decode CQ calls
  rc = qra64_do_decode(xdec,ix,pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz);
  if (rc>=0) return 1;    // decoded [cq/qrz ? ?]

  rc = qra64_do_decode(xdec, ix, pcodec->apmask_cqqrz_ooo,
		       pcodec->apmsg_cqqrz);
  if (rc>=0) return 2;    // decoded [cq ? ooo]

  // attempt to decode calls directed to us
  if (pcodec->apmsg_set[APTYPE_MYCALL]) {
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1,
		       pcodec->apmsg_call1);
	if (rc>=0) return 3;    // decoded [mycall ? ?]
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_ooo,
		       pcodec->apmsg_call1);
	if (rc>=0) return 4;    // decoded [mycall ? ooo]
	}

  // attempt to decode [mycall srccall ?] msgs
  if (pcodec->apmsg_set[APTYPE_BOTHCALLS]) {
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2,
		       pcodec->apmsg_call1_call2);
	if (rc>=0) return 5;    // decoded [mycall srccall ?]
	}

  // attempt to decode [? hiscall ?/b] msgs
  if (pcodec->apmsg_set[APTYPE_HISCALL]) {
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2,
		       pcodec->apmsg_call2);
	if (rc>=0) return 6;    // decoded [? hiscall ?]
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2_ooo,
		       pcodec->apmsg_call2);
	if (rc>=0) return 7;    // decoded [? hiscall ooo]
	}

  // attempt to decode [cq/qrz hiscall ?/b/grid] msgs
  if (pcodec->apmsg_set[APTYPE_CQHISCALL]) {

	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2,
				pcodec->apmsg_cq_call2);
	if (rc>=0) return 9;	// decoded [cq/qrz hiscall ?]

	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo,
		       pcodec->apmsg_cq_call2_grid);
	if (rc>=0) {
		// Full AP mask need special handling
		// To minimize false decodes we check the decoded message
		// with what passed in the ap_set call
		if (memcmp(pcodec->apmsg_cq_call2_grid,xdec, QRA64_K*sizeof(int))!=0)
			return -1;
		else
			return 11;		// decoded [cq/qrz hiscall grid]
		};

	rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo,
		       pcodec->apmsg_cq_call2);
	if (rc>=0) {
		// Full AP mask need special handling
		// To minimize false decodes we check the decoded message
		// with what passed in the ap_set call
		if (memcmp(pcodec->apmsg_cq_call2,xdec, QRA64_K*sizeof(int))!=0)
			return -1;
		else
			return 10;    // decoded [cq/qrz hiscall ]
		}
	}

  // attempt to decode [mycall hiscall grid]
  if (pcodec->apmsg_set[APTYPE_FULL]) {
	rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2_grid,
		       pcodec->apmsg_call1_call2_grid);
	if (rc>=0) {
		// Full AP mask need special handling
		// All the three msg fields were given.
		// To minimize false decodes we check the decoded message
		// with what passed in the ap_set call
		if (memcmp(pcodec->apmsg_call1_call2_grid,xdec, QRA64_K*sizeof(int))!=0)
			return -1;
		else
			return 8;	   // decoded [mycall hiscall grid]
		}
	}

  // all decoding attempts failed
  return rc;
}

// Decode with given a-priori information
static int qra64_do_decode(int *xdec, const float *pix, const int *ap_mask,
			   const int *ap_x)
{
  int rc;
  const float *ixsrc;
  float ix_masked[QRA64_NC*QRA64_M];  // Masked intrinsic information
  float ex[QRA64_NC*QRA64_M];	      // Extrinsic information from the decoder

  float v2cmsg[QRA64_NMSG*QRA64_M];   // buffers for the decoder messages
  float c2vmsg[QRA64_NMSG*QRA64_M];

  if (ap_mask==NULL) {   // no a-priori information
    ixsrc = pix;	 // intrinsic source is what passed as argument
  } else {
    // a-priori information provided
    // mask channel observations with a-priori
    ix_mask(ix_masked,pix,ap_mask,ap_x);
    ixsrc = ix_masked;	// intrinsic source is the masked version
  }

  // run the decoding algorithm
  rc = qra_extrinsic(&QRA64_CODE,ex,ixsrc,QRA64_NITER,v2cmsg,c2vmsg);
  if (rc<0)
    return -1;	// no convergence in given iterations

  // decode
  qra_mapdecode(&QRA64_CODE,xdec,ex,ixsrc);

  // verify crc
  if (calc_crc6(xdec,QRA64_K)!=xdec[QRA64_K]) // crc doesn't match (detected error)
    return -2;	// decoding was succesfull but crc doesn't match

  return 0;
}

// crc functions --------------------------------------------------------------
// crc-6 generator polynomial
// g(x) = x^6 + a5*x^5 + ... + a1*x + a0

// g(x) = x^6 + x + 1
#define CRC6_GEN_POL 0x30  // MSB=a0 LSB=a5

// g(x) = x^6 + x^2 + x + 1 (See:  https://users.ece.cmu.edu/~koopman/crc/)
// #define CRC6_GEN_POL 0x38  // MSB=a0 LSB=a5. Simulation results are similar

static int calc_crc6(const int *x, int sz)
{
  // todo: compute it faster using a look up table
  int k,j,t,sr = 0;
  for (k=0;k<sz;k++) {
    t = x[k];
    for (j=0;j<6;j++) {
      if ((t^sr)&0x01)
	sr = (sr>>1) ^ CRC6_GEN_POL;
      else
	sr = (sr>>1);
      t>>=1;
    }
  }
  return sr;
}

static void ix_mask(float *dst, const float *src, const int *mask,
		    const int *x)
{
  // mask intrinsic information (channel observations) with a priori knowledge

  int k,kk, smask;
  float *row;

  memcpy(dst,src,(QRA64_NC*QRA64_M)*sizeof(float));

  for (k=0;k<QRA64_K;k++) {	// we can mask only information symbols distrib
    smask = mask[k];
    row = PD_ROWADDR(dst,QRA64_M,k);
    if (smask) {
      for (kk=0;kk<QRA64_M;kk++)
	if (((kk^x[k])&smask)!=0)
	  *(row+kk) = 0.f;

      pd_norm(row,QRA64_m);
    }
  }
}

// encode/decode msgs as done in JT65
void encodemsg_jt65(int *y, const int call1, const int call2, const int grid)
{
  y[0]= (call1>>22)&0x3F;
  y[1]= (call1>>16)&0x3F;
  y[2]= (call1>>10)&0x3F;
  y[3]= (call1>>4)&0x3F;
  y[4]= (call1<<2)&0x3F;

  y[4] |= (call2>>26)&0x3F;
  y[5]= (call2>>20)&0x3F;
  y[6]= (call2>>14)&0x3F;
  y[7]= (call2>>8)&0x3F;
  y[8]= (call2>>2)&0x3F;
  y[9]= (call2<<4)&0x3F;

  y[9] |= (grid>>12)&0x3F;
  y[10]= (grid>>6)&0x3F;
  y[11]= (grid)&0x3F;

}
void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x)
{
  int nc1, nc2, ng;

  nc1 = x[4]>>2;
  nc1 |= x[3]<<4;
  nc1 |= x[2]<<10;
  nc1 |= x[1]<<16;
  nc1 |= x[0]<<22;

  nc2 = x[9]>>4;
  nc2 |= x[8]<<2;
  nc2 |= x[7]<<8;
  nc2 |= x[6]<<14;
  nc2 |= x[5]<<20;
  nc2 |= (x[4]&0x03)<<26;

  ng   = x[11];
  ng  |= x[10]<<6;
  ng  |= (x[9]&0x0F)<<12;

  *call1 = nc1;
  *call2 = nc2;
  *grid  = ng;
}


code:
//  (C) Copyright Runar Undheim, Robert Ramey & John Maddock 2008.
//  Use, modification and distribution are subject to the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt).
//
//  See http://www.boost.org/libs/type_traits for most recent version including documentation.

#ifndef BOOST_TT_HAS_NEW_OPERATOR_HPP_INCLUDED
#define BOOST_TT_HAS_NEW_OPERATOR_HPP_INCLUDED

#include <new> // std::nothrow_t
#include <cstddef> // std::size_t
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/detail/yes_no_type.hpp>
#include <boost/detail/workaround.hpp>

#if defined(new)
#  if BOOST_WORKAROUND(BOOST_MSVC, >= 1310)
#     define BOOST_TT_AUX_MACRO_NEW_DEFINED
#     pragma push_macro("new")
#     undef new
#  else
#     error "Sorry but you can't include this header if 'new' is defined as a macro."
#  endif
#endif

namespace boost {
namespace detail {
    template <class U, U x>
    struct test;

    template <typename T>
    struct has_new_operator_impl {
        template<class U>
        static type_traits::yes_type check_sig1(
            U*,
            test<
            void *(*)(std::size_t),
                &U::operator new
            >* = NULL
        );
        template<class U>
        static type_traits::no_type check_sig1(...);

        template<class U>
        static type_traits::yes_type check_sig2(
            U*,
            test<
            void *(*)(std::size_t, const std::nothrow_t&),
                &U::operator new
            >* = NULL
        );
        template<class U>
        static type_traits::no_type check_sig2(...);

        template<class U>
        static type_traits::yes_type check_sig3(
            U*,
            test<
            void *(*)(std::size_t, void*),
                &U::operator new
            >* = NULL
        );
        template<class U>
        static type_traits::no_type check_sig3(...);

        template<class U>
        static type_traits::yes_type check_sig4(
            U*,
            test<
            void *(*)(std::size_t),
                &U::operator new[]
            >* = NULL
        );
        template<class U>
        static type_traits::no_type check_sig4(...);

        template<class U>
        static type_traits::yes_type check_sig5(
            U*,
            test<
            void *(*)(std::size_t, const std::nothrow_t&),
                &U::operator new[]
            >* = NULL
        );
        template<class U>
        static type_traits::no_type check_sig5(...);

        template<class U>
        static type_traits::yes_type check_sig6(
            U*,
            test<
            void *(*)(std::size_t, void*),
                &U::operator new[]
            >* = NULL
        );
        template<class U>
        static type_traits::no_type check_sig6(...);

        // GCC2 won't even parse this template if we embed the computation
        // of s1 in the computation of value.
        #ifdef __GNUC__
            BOOST_STATIC_CONSTANT(unsigned, s1 = sizeof(has_new_operator_impl<T>::template check_sig1<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s2 = sizeof(has_new_operator_impl<T>::template check_sig2<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s3 = sizeof(has_new_operator_impl<T>::template check_sig3<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s4 = sizeof(has_new_operator_impl<T>::template check_sig4<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s5 = sizeof(has_new_operator_impl<T>::template check_sig5<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s6 = sizeof(has_new_operator_impl<T>::template check_sig6<T>(0)));
        #else
            #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
                #pragma warning(push)
                #pragma warning(disable:6334)
            #endif

            BOOST_STATIC_CONSTANT(unsigned, s1 = sizeof(check_sig1<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s2 = sizeof(check_sig2<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s3 = sizeof(check_sig3<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s4 = sizeof(check_sig4<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s5 = sizeof(check_sig5<T>(0)));
            BOOST_STATIC_CONSTANT(unsigned, s6 = sizeof(check_sig6<T>(0)));

            #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
                #pragma warning(pop)
            #endif
        #endif
        BOOST_STATIC_CONSTANT(bool, value =
            (s1 == sizeof(type_traits::yes_type)) ||
            (s2 == sizeof(type_traits::yes_type)) ||
            (s3 == sizeof(type_traits::yes_type)) ||
            (s4 == sizeof(type_traits::yes_type)) ||
            (s5 == sizeof(type_traits::yes_type)) ||
            (s6 == sizeof(type_traits::yes_type))
        );
    };
} // namespace detail

template <class T> struct has_new_operator : public integral_constant<bool, ::boost::detail::has_new_operator_impl<T>::value>{};

} // namespace boost

#if defined(BOOST_TT_AUX_MACRO_NEW_DEFINED)
#  pragma pop_macro("new")
#endif

#endif // BOOST_TT_HAS_NEW_OPERATOR_HPP_INCLUDED

license: mit


code:
/*
 [auto_generated]
 boost/numeric/odeint/config.hpp

 [begin_description]
 Sets configurations for odeint and used libraries. Should be included before any other odeint library
 [end_description]

 Copyright 2011-2012 Mario Mulansky
 Copyright 2011-2012 Karsten Ahnert

 Distributed under the Boost Software License, Version 1.0.
 (See accompanying file LICENSE_1_0.txt or
 copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_NUMERIC_ODEINT_CONFIG_HPP_INCLUDED
#define BOOST_NUMERIC_ODEINT_CONFIG_HPP_INCLUDED

//increase macro variable to allow rk78 scheme
#ifndef FUSION_MAX_VECTOR_SIZE
#define FUSION_MAX_VECTOR_SIZE 15
#endif

/*
 * the following definitions are only required if fusion vectors are used as state types
 * in the rk78 scheme
 * they should be defined by the user if required, see e.g. libs/numeric/examples/harmonic_oscillator_units.cpp
 */
#ifndef BOOST_FUSION_INVOKE_MAX_ARITY
#define BOOST_FUSION_INVOKE_MAX_ARITY 15
#endif

#ifndef BOOST_RESULT_OF_NUM_ARGS
#define BOOST_RESULT_OF_NUM_ARGS 15
#endif

#include <boost/config.hpp>

#if __cplusplus >= 201103L
#define BOOST_NUMERIC_ODEINT_CXX11 1
#endif

#endif // BOOST_NUMERIC_ODEINT_CONFIG_HPP_INCLUDED


code:
/*=============================================================================
    Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com)
    http://spirit.sourceforge.net/

  Distributed under the Boost Software License, Version 1.0. (See accompanying
  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef BOOST_SPIRIT_ACTOR_ASSIGN_KEY_ACTOR_HPP
#define BOOST_SPIRIT_ACTOR_ASSIGN_KEY_ACTOR_HPP

#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/actor/ref_const_ref_value_actor.hpp>
#include <boost/spirit/home/classic/actor/ref_const_ref_const_ref_a.hpp>

namespace boost { namespace spirit {

BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN

    struct assign_key_action
    {
        template<
            typename T,
            typename ValueT,
            typename KeyT
        >
        void act(T& ref_, ValueT const& value_, KeyT const& key_) const
        {
            ref_[ key_ ] = value_;
        }

        template<
            typename T,
            typename ValueT,
            typename IteratorT
        >
        void act(
            T& ref_,
            ValueT const& value_,
            IteratorT const& first_,
            IteratorT const& last_
            ) const
        {
            typedef typename T::key_type key_type;
            key_type key(first_,last_);

            ref_[key] = value_;
        }
    };

    template<
        typename T,
        typename ValueT
    >
    inline ref_const_ref_value_actor<T,ValueT,assign_key_action>
        assign_key_a(T& ref_, ValueT const& value_)
    {
        return ref_const_ref_value_actor<T,ValueT,assign_key_action>(
            ref_,
            value_
            );
    }

    template<
        typename T,
        typename ValueT,
        typename KeyT
    >
    inline ref_const_ref_const_ref_actor<
        T,
        ValueT,
        KeyT,
        assign_key_action
    >
        assign_key_a(
            T& ref_,
            ValueT const& value_,
            KeyT const& key_
    )
    {
        return ref_const_ref_const_ref_actor<
            T,
            ValueT,
            KeyT,
            assign_key_action
        >(
            ref_,
            value_,
            key_
            );
    }

BOOST_SPIRIT_CLASSIC_NAMESPACE_END

}}

#endif


code:
#ifndef BOOST_MPL_MAP_AUX_BEGIN_END_IMPL_HPP_INCLUDED
#define BOOST_MPL_MAP_AUX_BEGIN_END_IMPL_HPP_INCLUDED

// Copyright Aleksey Gurtovoy 2003-2004
// Copyright David Abrahams 2003-2004
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/mpl for documentation.

// $Id$
// $Date$
// $Revision$

#include <boost/mpl/begin_end_fwd.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/map/aux_/iterator.hpp>

namespace boost { namespace mpl {

template<>
struct begin_impl< aux::map_tag >
{
    template< typename Map > struct apply
    {
        typedef typename next< typename Map::order >::type max_order_;
        typedef m_iter<
              Map
            , next_order<Map,1,max_order_::value>::value
            , max_order_::value
            > type;
    };
};

template<>
struct end_impl< aux::map_tag >
{
    template< typename Map > struct apply
    {
        typedef typename next< typename Map::order >::type max_order_;
        typedef m_iter< Map,max_order_::value,max_order_::value > type;
    };
};

}}

#endif // BOOST_MPL_MAP_AUX_BEGIN_END_IMPL_HPP_INCLUDED


code:
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef PROXY_DWA2002615_HPP
# define PROXY_DWA2002615_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/object_core.hpp>
# include <boost/python/object_operators.hpp>

namespace boost { namespace python { namespace api {

template <class Policies>
class proxy : public object_operators<proxy<Policies> >
{
    typedef typename Policies::key_type key_type;

    typedef proxy const& assignment_self;
 public:
    proxy(object const& target, key_type const& key);
    operator object() const;

    // to support a[b] = c[d]
    proxy const& operator=(assignment_self) const;

    template <class T>
    inline proxy const& operator=(T const& rhs) const
    {
        Policies::set(m_target, m_key, object(rhs));
        return *this;
    }

 public: // implementation detail
    void del() const;

 private:
    object m_target;
    key_type m_key;
};

template <class T>
inline void del(proxy<T> const& x)
{
    x.del();
}

//
// implementation
//

template <class Policies>
inline proxy<Policies>::proxy(object const& target, key_type const& key)
    : m_target(target), m_key(key)
{}

template <class Policies>
inline proxy<Policies>::operator object() const
{
    return Policies::get(m_target, m_key);
}

// to support a[b] = c[d]
template <class Policies>
inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::assignment_self rhs) const
{
    return *this = python::object(rhs);
}

# define BOOST_PYTHON_PROXY_INPLACE(op)                                         \
template <class Policies, class R>                                              \
proxy<Policies> const& operator op(proxy<Policies> const& lhs, R const& rhs)    \
{                                                                               \
    object old(lhs);                                                            \
    return lhs = (old op rhs);                                                  \
}
BOOST_PYTHON_PROXY_INPLACE(+=)
BOOST_PYTHON_PROXY_INPLACE(-=)
BOOST_PYTHON_PROXY_INPLACE(*=)
BOOST_PYTHON_PROXY_INPLACE(/=)
BOOST_PYTHON_PROXY_INPLACE(%=)
BOOST_PYTHON_PROXY_INPLACE(<<=)
BOOST_PYTHON_PROXY_INPLACE(>>=)
BOOST_PYTHON_PROXY_INPLACE(&=)
BOOST_PYTHON_PROXY_INPLACE(^=)
BOOST_PYTHON_PROXY_INPLACE(|=)
# undef BOOST_PYTHON_PROXY_INPLACE

template <class Policies>
inline void proxy<Policies>::del() const
{
    Policies::del(m_target, m_key);
}

}}} // namespace boost::python::api

#endif // PROXY_DWA2002615_HPP


code:
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef INSTANCE_HOLDER_DWA2002517_HPP
# define INSTANCE_HOLDER_DWA2002517_HPP

# include <boost/python/detail/prefix.hpp>

# include <boost/noncopyable.hpp>
# include <boost/python/type_id.hpp>
# include <cstddef>

namespace boost { namespace python {

// Base class for all holders
struct BOOST_PYTHON_DECL instance_holder : private noncopyable
{
 public:
    instance_holder();
    virtual ~instance_holder();

    // return the next holder in a chain
    instance_holder* next() const;

    // When the derived holder actually holds by [smart] pointer and
    // null_ptr_only is set, only report that the type is held when
    // the pointer is null.  This is needed for proper shared_ptr
    // support, to prevent holding shared_ptrs from being found when
    // converting from python so that we can use the conversion method
    // that always holds the Python object.
    virtual void* holds(type_info, bool null_ptr_only) = 0;

    void install(PyObject* inst) throw();

    // These functions should probably be located elsewhere.

    // Allocate storage for an object of the given size at the given
    // offset in the Python instance<> object if bytes are available
    // there. Otherwise allocate size bytes of heap memory.
    static void* allocate(PyObject*, std::size_t offset, std::size_t size);

    // Deallocate storage from the heap if it was not carved out of
    // the given Python object by allocate(), above.
    static void deallocate(PyObject*, void* storage) throw();
 private:
    instance_holder* m_next;
};

// This macro is needed for implementation of derived holders
# define BOOST_PYTHON_UNFORWARD(N,ignored) (typename unforward<A##N>::type)(a##N)

//
// implementation
//
inline instance_holder* instance_holder::next() const
{
    return m_next;
}

}} // namespace boost::python

#endif // INSTANCE_HOLDER_DWA2002517_HPP


code:
// Boost.Function library

//  Copyright Douglas Gregor 2002-2003. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

// For more information, see http://www.boost.org

#define BOOST_FUNCTION_NUM_ARGS 8
#include <boost/function/detail/maybe_include.hpp>
#undef BOOST_FUNCTION_NUM_ARGS


code:
#if !BOOST_PHOENIX_IS_ITERATING

#ifndef BOOST_PHOENIX_STATEMENT_DETAIL_CATCH_PUSH_BACK_HPP
#define BOOST_PHOENIX_STATEMENT_DETAIL_CATCH_PUSH_BACK_HPP

#include <boost/phoenix/support/iterate.hpp>

#if !defined(BOOST_PHOENIX_DONT_USE_PREPROCESSED_FILES)

#include <boost/phoenix/statement/detail/preprocessed/catch_push_back.hpp>

#else

#if defined(__WAVE__) && defined(BOOST_PHOENIX_CREATE_PREPROCESSED_FILES)
#pragma wave option(preserve: 2, line: 0, output: "preprocessed/catch_push_back_" BOOST_PHOENIX_LIMIT_STR ".hpp")
#endif

/*==============================================================================
    Copyright (c) 2005-2010 Joel de Guzman
    Copyright (c) 2010 Thomas Heller

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#if defined(__WAVE__) && defined(BOOST_PHOENIX_CREATE_PREPROCESSED_FILES)
#pragma wave option(preserve: 1)
#endif

    #define BOOST_PHOENIX_CATCH_PUSH_BACK_R0(Z, N, DATA)                        \
        BOOST_PP_COMMA_IF(N)                                                    \
        typename proto::result_of::child_c<TryCatch, N>::type                   \
    /**/

    #define BOOST_PHOENIX_CATCH_PUSH_BACK_R1(Z, N, DATA)                        \
        BOOST_PP_COMMA_IF(N) proto::child_c<N>(try_catch)                       \
    /**/

#define BOOST_PHOENIX_ITERATION_PARAMS                                          \
        (3, (2, BOOST_PHOENIX_CATCH_LIMIT,                                      \
        <boost/phoenix/statement/detail/catch_push_back.hpp>))
#include BOOST_PHOENIX_ITERATE()

    #undef BOOST_PHOENIX_CATCH_PUSH_BACK_R0
    #undef BOOST_PHOENIX_CATCH_PUSH_BACK_R1

#if defined(__WAVE__) && defined(BOOST_PHOENIX_CREATE_PREPROCESSED_FILES)
#pragma wave option(output: null)
#endif

#endif // BOOST_PHOENIX_DONT_USE_PREPROCESSED_FILES

#endif

#else
        template <typename TryCatch, typename Exception, typename Capture, typename Expr>
        struct catch_push_back<TryCatch, Exception, Capture, Expr, BOOST_PHOENIX_ITERATION>
        {
            typedef
                typename proto::result_of::make_expr<
                    phoenix::tag::catch_
                  , proto::basic_default_domain
                  , catch_exception<Exception>
                  , Capture
                  , Expr
                >::type
                catch_expr;

            typedef phoenix::expression::try_catch<
                BOOST_PP_REPEAT(BOOST_PHOENIX_ITERATION, BOOST_PHOENIX_CATCH_PUSH_BACK_R0, _)
              , catch_expr> gen_type;
            typedef typename gen_type::type type;

            static type
            make(
                TryCatch const& try_catch
              , Capture const& capture
              , Expr const& catch_
            )
            {
                return
                    gen_type::make(
                        BOOST_PP_REPEAT(
                            BOOST_PHOENIX_ITERATION
                          , BOOST_PHOENIX_CATCH_PUSH_BACK_R1
                          , _
                        )
                      , proto::make_expr<
                            phoenix::tag::catch_
                          , proto::basic_default_domain
                        >(catch_exception<Exception>(), capture, catch_)
                    );
            }
        };

        template <typename TryCatch, typename Exception, typename Expr>
        struct catch_push_back<TryCatch, Exception, void, Expr, BOOST_PHOENIX_ITERATION>
        {
            typedef
                typename proto::result_of::make_expr<
                    phoenix::tag::catch_
                  , proto::basic_default_domain
                  , catch_exception<Exception>
                  , Expr
                >::type
                catch_expr;

            typedef phoenix::expression::try_catch<
                BOOST_PP_REPEAT(BOOST_PHOENIX_ITERATION, BOOST_PHOENIX_CATCH_PUSH_BACK_R0, _)
              , catch_expr> gen_type;
            typedef typename gen_type::type type;

            static type
            make(
                TryCatch const& try_catch
              , Expr const& catch_
            )
            {
                return
                    gen_type::make(
                        BOOST_PP_REPEAT(
                            BOOST_PHOENIX_ITERATION
                          , BOOST_PHOENIX_CATCH_PUSH_BACK_R1
                          , _
                        )
                      , proto::make_expr<
                            phoenix::tag::catch_
                          , proto::basic_default_domain
                        >(catch_exception<Exception>(), catch_)
                    );
            }
        };

        template <typename TryCatch, typename Expr>
        struct catch_all_push_back<TryCatch, Expr, BOOST_PHOENIX_ITERATION>
        {
            typedef
                typename proto::result_of::make_expr<
                    phoenix::tag::catch_all
                  , proto::basic_default_domain
                  , Expr
                >::type
                catch_expr;

            typedef phoenix::expression::try_catch<
                BOOST_PP_REPEAT(BOOST_PHOENIX_ITERATION, BOOST_PHOENIX_CATCH_PUSH_BACK_R0, _)
              , catch_expr> gen_type;
            typedef typename gen_type::type type;

            static type
            make(
                TryCatch const& try_catch
              , Expr const& catch_
            )
            {
                return
                    gen_type::make(
                        BOOST_PP_REPEAT(
                            BOOST_PHOENIX_ITERATION
                          , BOOST_PHOENIX_CATCH_PUSH_BACK_R1
                          , _
                        )
                      , proto::make_expr<
                            phoenix::tag::catch_all
                          , proto::basic_default_domain
                        >(catch_)
                    );
            }
        };

#endif


code:
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP

#ifndef BOOST_CONFIG_HPP
#  include <boost/config.hpp>
#endif

#if defined(BOOST_HAS_PRAGMA_ONCE)
#  pragma once
#endif

#if    !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\
    && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
   #define BOOST_CONTAINER_PERFECT_FORWARDING
#endif

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\
    && (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ < 40700)
   #define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST
#endif

#if defined(BOOST_GCC_VERSION)
#  if (BOOST_GCC_VERSION < 40700) || !defined(BOOST_GCC_CXX11)
#     define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
#  endif
#elif defined(BOOST_MSVC)
#  if _MSC_FULL_VER < 180020827
#     define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
#  endif
#elif defined(BOOST_CLANG)
#  if !__has_feature(cxx_delegating_constructors)
#     define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
#  endif
#endif

#if !defined(BOOST_FALLTHOUGH)
   #define BOOST_CONTAINER_FALLTHOUGH
#else
   #define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
#endif

#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
#endif

//Macros for documentation purposes. For code, expands to the argument
#define BOOST_CONTAINER_IMPDEF(TYPE) TYPE
#define BOOST_CONTAINER_SEEDOC(TYPE) TYPE

//Macros for memset optimization. In most platforms
//memsetting pointers and floatings is safe and faster.
//
//If your platform does not offer these guarantees
//define these to value zero.
#ifndef BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_NOT_ZERO
#define BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO 1
#endif

#ifndef BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_NULL
#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL
#endif

#define BOOST_CONTAINER_DOC1ST(TYPE1, TYPE2) TYPE2
#define BOOST_CONTAINER_I ,
#define BOOST_CONTAINER_DOCIGN(T) T
#define BOOST_CONTAINER_DOCONLY(T)

/*
   we need to import/export our code only if the user has specifically
   asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
   libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
   if they want just this one to be dynamically liked:
*/
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)

   /* export if this is our own source, otherwise import: */
   #ifdef BOOST_CONTAINER_SOURCE
   #  define BOOST_CONTAINER_DECL BOOST_SYMBOL_EXPORT
   #else
   #  define BOOST_CONTAINER_DECL BOOST_SYMBOL_IMPORT

   #endif  /* BOOST_CONTAINER_SOURCE */
#else
   #define BOOST_CONTAINER_DECL
#endif  /* DYN_LINK */

//#define BOOST_CONTAINER_DISABLE_FORCEINLINE

#if defined(BOOST_CONTAINER_DISABLE_FORCEINLINE)
   #define BOOST_CONTAINER_FORCEINLINE inline
#elif defined(BOOST_CONTAINER_FORCEINLINE_IS_BOOST_FORCELINE)
   #define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
#elif defined(BOOST_MSVC) && defined(_DEBUG)
   //"__forceinline" and MSVC seems to have some bugs in debug mode
   #define BOOST_CONTAINER_FORCEINLINE inline
#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
   //Older GCCs have problems with forceinline
   #define BOOST_CONTAINER_FORCEINLINE inline
#else
   #define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
#endif

#endif   //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP


code:
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
// Parts of the pthread code come from Boost Threads code.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_INTERPROCESS_MUTEX_HPP
#define BOOST_INTERPROCESS_MUTEX_HPP

#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

#ifndef BOOST_CONFIG_HPP
#  include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
#  pragma once
#endif

#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/assert.hpp>

#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
   #include <boost/interprocess/sync/posix/mutex.hpp>
   #define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
   #include <boost/interprocess/sync/windows/mutex.hpp>
   #define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
   #include <boost/interprocess/sync/spin/mutex.hpp>
   #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION

namespace boost {
namespace interprocess {
namespace ipcdetail{
namespace robust_emulation_helpers {

template<class T>
class mutex_traits;

}}}}

#endif

#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

//!\file
//!Describes a mutex class that can be placed in memory shared by
//!several processes.

namespace boost {
namespace interprocess {

class interprocess_condition;

//!Wraps a interprocess_mutex that can be placed in shared memory and can be
//!shared between processes. Allows timed lock tries
class interprocess_mutex
{
   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
   //Non-copyable
   interprocess_mutex(const interprocess_mutex &);
   interprocess_mutex &operator=(const interprocess_mutex &);
   friend class interprocess_condition;

   public:
   #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
      #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
      typedef ipcdetail::spin_mutex internal_mutex_type;
      private:
      friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
      void take_ownership(){ m_mutex.take_ownership(); }
      public:
   #elif defined(BOOST_INTERPROCESS_USE_POSIX)
      #undef BOOST_INTERPROCESS_USE_POSIX
      typedef ipcdetail::posix_mutex internal_mutex_type;
   #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
      #undef BOOST_INTERPROCESS_USE_WINDOWS
      typedef ipcdetail::windows_mutex internal_mutex_type;
   #else
      #error "Unknown platform for interprocess_mutex"
   #endif

   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
   public:

   //!Constructor.
   //!Throws interprocess_exception on error.
   interprocess_mutex();

   //!Destructor. If any process uses the mutex after the destructor is called
   //!the result is undefined. Does not throw.
   ~interprocess_mutex();

   //!Effects: The calling thread tries to obtain ownership of the mutex, and
   //!   if another thread has ownership of the mutex, it waits until it can
   //!   obtain the ownership. If a thread takes ownership of the mutex the
   //!   mutex must be unlocked by the same mutex.
   //!Throws: interprocess_exception on error.
   void lock();

   //!Effects: The calling thread tries to obtain ownership of the mutex, and
   //!   if another thread has ownership of the mutex returns immediately.
   //!Returns: If the thread acquires ownership of the mutex, returns true, if
   //!   the another thread has ownership of the mutex, returns false.
   //!Throws: interprocess_exception on error.
   bool try_lock();

   //!Effects: The calling thread will try to obtain exclusive ownership of the
   //!   mutex if it can do so in until the specified time is reached. If the
   //!   mutex supports recursive locking, the mutex must be unlocked the same
   //!   number of times it is locked.
   //!Returns: If the thread acquires ownership of the mutex, returns true, if
   //!   the timeout expires returns false.
   //!Throws: interprocess_exception on error.
   bool timed_lock(const boost::posix_time::ptime &abs_time);

   //!Effects: The calling thread releases the exclusive ownership of the mutex.
   //!Throws: interprocess_exception on error.
   void unlock();

   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
   internal_mutex_type &internal_mutex()
   {  return m_mutex;   }

   const internal_mutex_type &internal_mutex() const
   {  return m_mutex;   }

   private:
   internal_mutex_type m_mutex;
   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};

}  //namespace interprocess {
}  //namespace boost {

namespace boost {
namespace interprocess {

inline interprocess_mutex::interprocess_mutex(){}

inline interprocess_mutex::~interprocess_mutex(){}

inline void interprocess_mutex::lock()
{
   #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
      boost::posix_time::ptime wait_time
         = microsec_clock::universal_time()
         + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
      if (!m_mutex.timed_lock(wait_time))
      {
         throw interprocess_exception(timeout_when_locking_error
                                     , "Interprocess mutex timeout when locking. Possible deadlock: "
                                       "owner died without unlocking?");
      }
   #else
      m_mutex.lock();
   #endif
}

inline bool interprocess_mutex::try_lock()
{ return m_mutex.try_lock(); }

inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{ return m_mutex.timed_lock(abs_time); }

inline void interprocess_mutex::unlock()
{ m_mutex.unlock(); }

}  //namespace interprocess {
}  //namespace boost {

#include <boost/interprocess/detail/config_end.hpp>

#endif   //BOOST_INTERPROCESS_MUTEX_HPP


code:
/*
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * Copyright (c) 2009 Helge Bahmann
 * Copyright (c) 2013 Tim Blechmann
 * Copyright (c) 2014 Andrey Semashev
 */
/*!
 * \file   atomic/detail/ops_gcc_ppc.hpp
 *
 * This header contains implementation of the \c operations template.
 */

#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_

#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {
namespace atomics {
namespace detail {

// The implementation below uses information from this document:
// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2010.02.19a.html

/*
    Refer to: Motorola: "Programming Environments Manual for 32-Bit
    Implementations of the PowerPC Architecture", Appendix E:
    "Synchronization Programming Examples" for an explanation of what is
    going on here (can be found on the web at various places by the
    name "MPCFPE32B.pdf", Google is your friend...)

    Most of the atomic operations map to instructions in a relatively
    straight-forward fashion, but "load"s may at first glance appear
    a bit strange as they map to:

            lwz %rX, addr
            cmpw %rX, %rX
            bne- 1f
        1:

    That is, the CPU is forced to perform a branch that "formally" depends
    on the value retrieved from memory. This scheme has an overhead of
    about 1-2 clock cycles per load, but it allows to map "acquire" to
    the "isync" instruction instead of "sync" uniformly and for all type
    of atomic operations. Since "isync" has a cost of about 15 clock
    cycles, while "sync" hast a cost of about 50 clock cycles, the small
    penalty to atomic loads more than compensates for this.

    Byte- and halfword-sized atomic values are realized by encoding the
    value to be represented into a word, performing sign/zero extension
    as appropriate. This means that after add/sub operations the value
    needs fixing up to accurately preserve the wrap-around semantic of
    the smaller type. (Nothing special needs to be done for the bit-wise
    and the "exchange type" operators as the compiler already sees to
    it that values carried in registers are extended appropriately and
    everything falls into place naturally).

    The register constraint "b"  instructs gcc to use any register
    except r0; this is sometimes required because the encoding for
    r0 is used to signify "constant zero" in a number of instructions,
    making r0 unusable in this place. For simplicity this constraint
    is used everywhere since I am to lazy to look this up on a
    per-instruction basis, and ppc has enough registers for this not
    to pose a problem.
*/

// A note about memory_order_consume. Technically, this architecture allows to avoid
// unnecessary memory barrier after consume load since it supports data dependency ordering.
// However, some compiler optimizations may break a seemingly valid code relying on data
// dependency tracking by injecting bogus branches to aid out of order execution.
// This may happen not only in Boost.Atomic code but also in user's code, which we have no
// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
// For this reason we promote memory_order_consume to memory_order_acquire.

struct gcc_ppc_operations_base
{
    static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;

    static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
    {
#if defined(__powerpc64__) || defined(__PPC64__)
        if (order == memory_order_seq_cst)
            __asm__ __volatile__ ("sync" ::: "memory");
        else if ((order & memory_order_release) != 0)
            __asm__ __volatile__ ("lwsync" ::: "memory");
#else
        if ((order & memory_order_release) != 0)
            __asm__ __volatile__ ("sync" ::: "memory");
#endif
    }

    static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
    {
        if ((order & (memory_order_consume | memory_order_acquire)) != 0)
            __asm__ __volatile__ ("isync" ::: "memory");
    }
};

template< bool Signed >
struct operations< 4u, Signed > :
    public gcc_ppc_operations_base
{
    typedef typename make_storage_type< 4u, Signed >::type storage_type;
    typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;

    static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        fence_before(order);
        __asm__ __volatile__
        (
            "stw %1, %0\n\t"
            : "+m" (storage)
            : "r" (v)
        );
    }

    static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
    {
        storage_type v;
        if (order == memory_order_seq_cst)
            __asm__ __volatile__ ("sync" ::: "memory");
        if ((order & (memory_order_consume | memory_order_acquire)) != 0)
        {
            __asm__ __volatile__
            (
                "lwz %0, %1\n\t"
                "cmpw %0, %0\n\t"
                "bne- 1f\n\t"
                "1:\n\t"
                "isync\n\t"
                : "=&r" (v)
                : "m" (storage)
                : "cr0", "memory"
            );
        }
        else
        {
            __asm__ __volatile__
            (
                "lwz %0, %1\n\t"
                : "=&r" (v)
                : "m" (storage)
            );
        }
        return v;
    }

    static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y1\n\t"
            "stwcx. %2,%y1\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "+Z" (storage)
            : "b" (v)
            : "cr0"
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE bool compare_exchange_weak(
        storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
    {
        int success;
        fence_before(success_order);
        __asm__ __volatile__
        (
            "li %1, 0\n\t"
            "lwarx %0,%y2\n\t"
            "cmpw %0, %3\n\t"
            "bne- 1f\n\t"
            "stwcx. %4,%y2\n\t"
            "bne- 1f\n\t"
            "li %1, 1\n\t"
            "1:\n\t"
            : "=&b" (expected), "=&b" (success), "+Z" (storage)
            : "b" (expected), "b" (desired)
            : "cr0"
        );
        if (success)
            fence_after(success_order);
        else
            fence_after(failure_order);
        return !!success;
    }

    static BOOST_FORCEINLINE bool compare_exchange_strong(
        storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
    {
        int success;
        fence_before(success_order);
        __asm__ __volatile__
        (
            "li %1, 0\n\t"
            "0: lwarx %0,%y2\n\t"
            "cmpw %0, %3\n\t"
            "bne- 1f\n\t"
            "stwcx. %4,%y2\n\t"
            "bne- 0b\n\t"
            "li %1, 1\n\t"
            "1:\n\t"
            : "=&b" (expected), "=&b" (success), "+Z" (storage)
            : "b" (expected), "b" (desired)
            : "cr0"
        );
        if (success)
            fence_after(success_order);
        else
            fence_after(failure_order);
        return !!success;
    }

    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "add %1,%0,%3\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "sub %1,%0,%3\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "and %1,%0,%3\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "or %1,%0,%3\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "xor %1,%0,%3\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
    {
        return !!exchange(storage, (storage_type)1, order);
    }

    static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
    {
        store(storage, 0, order);
    }

    static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
    {
        return true;
    }
};

template< >
struct operations< 1u, false > :
    public operations< 4u, false >
{
    typedef operations< 4u, false > base_type;
    typedef base_type::storage_type storage_type;

    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "add %1,%0,%3\n\t"
            "rlwinm %1, %1, 0, 0xff\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "sub %1,%0,%3\n\t"
            "rlwinm %1, %1, 0, 0xff\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }
};

template< >
struct operations< 1u, true > :
    public operations< 4u, true >
{
    typedef operations< 4u, true > base_type;
    typedef base_type::storage_type storage_type;

    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "add %1,%0,%3\n\t"
            "extsb %1, %1\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "sub %1,%0,%3\n\t"
            "extsb %1, %1\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }
};

template< >
struct operations< 2u, false > :
    public operations< 4u, false >
{
    typedef operations< 4u, false > base_type;
    typedef base_type::storage_type storage_type;

    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "add %1,%0,%3\n\t"
            "rlwinm %1, %1, 0, 0xffff\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "sub %1,%0,%3\n\t"
            "rlwinm %1, %1, 0, 0xffff\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }
};

template< >
struct operations< 2u, true > :
    public operations< 4u, true >
{
    typedef operations< 4u, true > base_type;
    typedef base_type::storage_type storage_type;

    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "add %1,%0,%3\n\t"
            "extsh %1, %1\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "lwarx %0,%y2\n\t"
            "sub %1,%0,%3\n\t"
            "extsh %1, %1\n\t"
            "stwcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }
};

#if defined(__powerpc64__) || defined(__PPC64__)

template< bool Signed >
struct operations< 8u, Signed > :
    public gcc_ppc_operations_base
{
    typedef typename make_storage_type< 8u, Signed >::type storage_type;
    typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;

    static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        fence_before(order);
        __asm__ __volatile__
        (
            "std %1, %0\n\t"
            : "+m" (storage)
            : "r" (v)
        );
    }

    static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
    {
        storage_type v;
        if (order == memory_order_seq_cst)
            __asm__ __volatile__ ("sync" ::: "memory");
        if ((order & (memory_order_consume | memory_order_acquire)) != 0)
        {
            __asm__ __volatile__
            (
                "ld %0, %1\n\t"
                "cmpd %0, %0\n\t"
                "bne- 1f\n\t"
                "1:\n\t"
                "isync\n\t"
                : "=&b" (v)
                : "m" (storage)
                : "cr0", "memory"
            );
        }
        else
        {
            __asm__ __volatile__
            (
                "ld %0, %1\n\t"
                : "=&b" (v)
                : "m" (storage)
            );
        }
        return v;
    }

    static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "ldarx %0,%y1\n\t"
            "stdcx. %2,%y1\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "+Z" (storage)
            : "b" (v)
            : "cr0"
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE bool compare_exchange_weak(
        storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
    {
        int success;
        fence_before(success_order);
        __asm__ __volatile__
        (
            "li %1, 0\n\t"
            "ldarx %0,%y2\n\t"
            "cmpd %0, %3\n\t"
            "bne- 1f\n\t"
            "stdcx. %4,%y2\n\t"
            "bne- 1f\n\t"
            "li %1, 1\n\t"
            "1:"
            : "=&b" (expected), "=&b" (success), "+Z" (storage)
            : "b" (expected), "b" (desired)
            : "cr0"
        );
        if (success)
            fence_after(success_order);
        else
            fence_after(failure_order);
        return !!success;
    }

    static BOOST_FORCEINLINE bool compare_exchange_strong(
        storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
    {
        int success;
        fence_before(success_order);
        __asm__ __volatile__
        (
            "li %1, 0\n\t"
            "0: ldarx %0,%y2\n\t"
            "cmpd %0, %3\n\t"
            "bne- 1f\n\t"
            "stdcx. %4,%y2\n\t"
            "bne- 0b\n\t"
            "li %1, 1\n\t"
            "1:\n\t"
            : "=&b" (expected), "=&b" (success), "+Z" (storage)
            : "b" (expected), "b" (desired)
            : "cr0"
        );
        if (success)
            fence_after(success_order);
        else
            fence_after(failure_order);
        return !!success;
    }

    static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "ldarx %0,%y2\n\t"
            "add %1,%0,%3\n\t"
            "stdcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "ldarx %0,%y2\n\t"
            "sub %1,%0,%3\n\t"
            "stdcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "ldarx %0,%y2\n\t"
            "and %1,%0,%3\n\t"
            "stdcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "ldarx %0,%y2\n\t"
            "or %1,%0,%3\n\t"
            "stdcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
    {
        storage_type original, tmp;
        fence_before(order);
        __asm__ __volatile__
        (
            "1:\n\t"
            "ldarx %0,%y2\n\t"
            "xor %1,%0,%3\n\t"
            "stdcx. %1,%y2\n\t"
            "bne- 1b\n\t"
            : "=&b" (original), "=&b" (tmp), "+Z" (storage)
            : "b" (v)
            : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
        );
        fence_after(order);
        return original;
    }

    static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
    {
        return !!exchange(storage, (storage_type)1, order);
    }

    static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
    {
        store(storage, 0, order);
    }

    static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
    {
        return true;
    }
};

#endif // defined(__powerpc64__) || defined(__PPC64__)

BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
    switch (order)
    {
    case memory_order_consume:
    case memory_order_acquire:
    case memory_order_release:
    case memory_order_acq_rel:
#if defined(__powerpc64__) || defined(__PPC64__)
        __asm__ __volatile__ ("lwsync" ::: "memory");
        break;
#endif
    case memory_order_seq_cst:
        __asm__ __volatile__ ("sync" ::: "memory");
        break;
    default:;
    }
}

BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
    if (order != memory_order_relaxed)
#if defined(__ibmxl__) || defined(__IBMCPP__)
        __fence();
#else
        __asm__ __volatile__ ("" ::: "memory");
#endif
}

} // namespace detail
} // namespace atomics
} // namespace boost

#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_


code:
// Three-state boolean logic library

// Copyright Douglas Gregor 2002-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// For more information, see http://www.boost.org
#ifndef BOOST_LOGIC_TRIBOOL_FWD_HPP
#define BOOST_LOGIC_TRIBOOL_FWD_HPP

namespace boost { namespace logic { class tribool; } }

#endif // BOOST_LOGIC_TRIBOOL_FWD_HPP


code:
// -- select_functions.hpp -- Boost Lambda Library --------------------------

// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org

#ifndef BOOST_LAMBDA_SELECT_FUNCTIONS_HPP
#define BOOST_LAMBDA_SELECT_FUNCTIONS_HPP

namespace boost {
namespace lambda {
namespace detail {

// select functions -------------------------------
template<class Any, CALL_TEMPLATE_ARGS>
inline Any& select(Any& any, CALL_FORMAL_ARGS) { CALL_USE_ARGS; return any; }

template<class Arg, CALL_TEMPLATE_ARGS>
inline typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
select ( const lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
  return op.template call<
    typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
  >(CALL_ACTUAL_ARGS);
}
template<class Arg, CALL_TEMPLATE_ARGS>
inline typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
select ( lambda_functor<Arg>& op, CALL_FORMAL_ARGS) {
  return op.template call<
    typename Arg::template sig<tuple<CALL_REFERENCE_TYPES> >::type
  >(CALL_ACTUAL_ARGS);
}

// ------------------------------------------------------------------------
// select functions where the return type is explicitly given
// Note: on many functions, this return type is just discarded.
// The select functions are inside a class template, and the return type
// is a class template argument.
// The first implementation used function templates with an explicitly
// specified template parameter.
// However, this resulted in ambiguous calls (at least with gcc 2.95.2
// and edg 2.44). Not sure whether the compilers were right or wrong.

template<class RET> struct r_select {

// Any == RET
  template<class Any, CALL_TEMPLATE_ARGS>
  static
  inline RET go (Any& any, CALL_FORMAL_ARGS) { CALL_USE_ARGS; return any; }

  template<class Arg, CALL_TEMPLATE_ARGS>
  static
  inline RET go (const lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
    return op.template call<RET>(CALL_ACTUAL_ARGS);
  }
  template<class Arg, CALL_TEMPLATE_ARGS>
  static
  inline RET go (lambda_functor<Arg>& op, CALL_FORMAL_ARGS ) {
    return op.template call<RET>(CALL_ACTUAL_ARGS);
  }
};

} // namespace detail
} // namespace lambda
} // namespace boost

#endif


code:
function stdmsg(msg0,bcontest,mygrid)

  ! Is msg0 a standard "JT-style" message?

  use iso_c_binding, only: c_bool
  use packjt
  character*22 msg0,msg1,msg
  character*6 mygrid
  integer dat(12)
  logical(c_bool), value :: bcontest
  logical(c_bool) :: stdmsg

  msg1=msg0
  i0=index(msg1,' OOO ')
  if(i0.gt.10) msg1=msg0(1:i0)
  call packmsg(msg0,dat,itype,logical(bcontest))
  call unpackmsg(dat,msg,logical(bcontest),mygrid)
  stdmsg=(msg.eq.msg1) .and. (itype.ge.0) .and. itype.ne.6

  return
end function stdmsg