%% $RCSfile: sdsprandsrc2.tlc,v $ %% $Revision: 1.6 $ %% $Date: 2000/06/15 20:37:47 $ %% %% Copyright 1995-2000 The MathWorks, Inc. %% %% Abstract: Generate Uniform or Normal (Gaussian) Random Numbers %% %implements "sdsprandsrc2" "C" %% Function: BlockTypeSetup ================================================ %% Abstract: %% %function BlockTypeSetup(block, system) void %% Render a DSP_InitializeSeed function once for use by all sdsprandsrc blocks. %% Needed for both the Uniform and Gaussian cases. %% First, cache the function prototype for DSP_InitializeSeed: %% %openfile InitSeedBuff extern void DSP_InitializeSeed(uint32_T *urandSeed, real_T initSeed); %closefile InitSeedBuff % %% Next, cache the DSP_InitializeSeed function itself: %% %openfile InitSeedBuff /* Function: DSP_InitializeSeed * Bit-shift the given initial seed */ extern void DSP_InitializeSeed(uint32_T *urandSeed, real_T initSeed) { const uint32_T maxseed = 2147483646; /* 2^31-2 */ const uint32_T seed0 = 1144108930; /* Seed #6, starting from seed = 1 */ const uint32_T bit16 = 32768; /* 2^15 */ *urandSeed = (uint32_T)initSeed; /* Interchange bits 1-15 and 17-31 */ { int_T r = *urandSeed >> 16; int_T t = *urandSeed & bit16; *urandSeed = ((*urandSeed - (r << 16) - t) << 16) + t + r; } if (*urandSeed < 1) { *urandSeed = seed0; } if (*urandSeed > maxseed) { *urandSeed = maxseed; } } /* end DSP_InitializeSeed */ %closefile InitSeedBuff % %endfunction %% BlockTypeSetup %% Function: BlockInstanceSetup ================================================ %% Abstract: %% %function BlockInstanceSetup(block, system) void %assign src_type = block.SFcnParamSettings.SrcType %if src_type == "Uniform" % %else % % %endif %endfunction %% BlockInstanceSetup %% Function: RenderUniformRandFcn ============================================== %% Abstract: %% Render the DSP_UniformRand function and prototype. %% Only render the content ONCE. Any additional calls %% are simply ignored. %% %function RenderUniformRandFcn() void %assign database_entry = "sdsprandsrc_uniformrand_fcn" %assign model_cache = "::CompiledModel." + database_entry %% Check info so that we do not define this function more than once: %if !EXISTS("%") %% Retain definition to prevent multiple identical defines: %% %assign % = 1 %assign ::CompiledModel = ::CompiledModel + % %undef % %%Remove from block scope %% First, cache the function prototype for DSP_UniformRand: %% %% Render a DSP_UniformRand function once for use by all sdsprandsrc blocks. %openfile DSP_RandBuff /* DSP Blockset Random Source block Uniform random number generator */ extern real_T DSP_UniformRand(uint32_T *seed); %closefile DSP_RandBuff % %% Next, cache the DSP_UniformRand function itself: %% %openfile DSP_RandBuff /* * DSP Blockset Random Source block * Uniform random number generator * Generates random number in range (0,1) */ extern real_T DSP_UniformRand(uint32_T *seed) /* pointer to a running seed */ { const uint32_T IA = 16807; /* magic multiplier = 7^5 */ const uint32_T IM = 2147483647; /* modulus = 2^31-1 */ const uint32_T IQ = 127773; /* IM div IA */ const uint32_T IR = 2836; /* IM modulo IA */ const real_T S = 4.656612875245797e-10; /* reciprocal of 2^31-1 */ uint32_T hi = *seed / IQ; uint32_T lo = *seed % IQ; int32_T test = IA * lo - IR * hi; /* never overflows */ *seed = ((test < 0) ? (unsigned int)(test + IM) : (unsigned int)test); return( (real_T) ((*seed) * S) ); } /* end DSP_UniformRand */ %closefile DSP_RandBuff % %endif %endfunction %% RenderUniformRandFcn %% Function: RenderNormalRandFcn ============================================== %% Abstract: %% Render the DSP_NormalRand function and prototype. %% Only render the content ONCE. Any additional calls %% are simply ignored. %% %function RenderNormalRandFcn() void %assign database_entry = "sdsprandsrc_normrand_fcn" %assign model_cache = "::CompiledModel." + database_entry %% Check info so that we do not define this function more than once: %if !EXISTS("%") %% Retain definition to prevent multiple identical defines: %% %assign % = 1 %assign ::CompiledModel = ::CompiledModel + % %undef % %%Remove from block scope %% First, cache the function prototype for DSP_NormalRand: %% %openfile DSP_RandBuff /* DSP Blockset Random Source block Gaussian random number generator */ extern real_T DSP_NormalRand(uint32_T *seed); %closefile DSP_RandBuff % %% Next, cache the DSP_NormalRand function itself: %% %openfile DSP_RandBuff /* Function: DSP_NormalRand * Normal (Gaussian) random number generator */ extern real_T DSP_NormalRand(unsigned int *seed) { real_T sr, si, t; do { sr = 2.0 * DSP_UniformRand(seed) - 1.0; si = 2.0 * DSP_UniformRand(seed) - 1.0; t = sr * sr + si * si; } while (t > 1.0); return(sr * sqrt((-2.0 * log(t)) / t)); } /* end DSP_NormalRand */ %closefile DSP_RandBuff % %endif %endfunction %% RenderNormalRandFcn %% Function: ================================================ %% Abstract: Render the channel and frame loops and call to initialize the seed %% %function DSP_RenderInitializeSeedLoop(nchans,multipleChans,IS_COMPLEX,seedLen) Output %% %% if multipleChans %% { %% endif %if multipleChans int_T i; %if seedLen > 1 real_T *pSeeds = (real_T *)%; %endif for (i=0;i<%;i++) { %if seedLen > 1 real_T seedVal = pSeeds[i]; %endif %% For the single channel case, %% seedVal is set in DSP_Call_To_InitializeSeed function %endif %% %\ %% %if multipleChans %if seedLen == 1 seedVal += 2.0; %endif } %endif %% if multipleChans %% } %% endif %endfunction %% DSP_RenderInitializeSeedLoop %% Function: ================================================ %% Abstract: Call the function to initialize the seeds based on complexity %% %function DSP_Call_To_InitializeSeed(multipleChans,IS_COMPLEX,seedLen) Output %% %if seedLen == 1 %assign pSeeds = SFcnParamSettings.InitSeed %endif %if (IS_COMPLEX) %if multipleChans DSP_InitializeSeed(&urandSeed->re,seedVal); DSP_InitializeSeed(&urandSeed->im,seedVal+1); urandSeed++; %else DSP_InitializeSeed((uint32_T *)%.re,%); DSP_InitializeSeed((uint32_T *)%.im,%+1); %endif %else %if multipleChans DSP_InitializeSeed(urandSeed++,seedVal); %else DSP_InitializeSeed((uint32_T *)%,%); %endif %endif %endfunction %% DSP_Call_To_InitializeSeed %% Function: ================================================ %% Abstract: %function DSP_CallRandomNumberGenerator(IS_COMPLEX,IS_UNIFORM) Output %% %if (IS_COMPLEX) %if (IS_UNIFORM) /* Generate complex uniform random numbers */ y->re = DSP_UniformRand(&urandSeed->re) * (*pMax - *pMin) + *pMin; (y++)->im = DSP_UniformRand(&urandSeed->im) * (*pMax - *pMin) + *pMin; %else /* Generate complex normal (gaussian) random numbers */ %assign isMeanComplex = CAST("Boolean",(Mean.ComplexSignal == "yes")) %if (isMeanComplex) y->re = DSP_NormalRand(&urandSeed->re) * sqrt(*pVar/2) + pMean->re; (y++)->im = DSP_NormalRand(&urandSeed->im) * sqrt(*pVar/2) + pMean->im; %else y->re = DSP_NormalRand(&urandSeed->re) * sqrt(*pVar/2) + *pMean; (y++)->im = DSP_NormalRand(&urandSeed->im) * sqrt(*pVar/2); %endif %endif %else %% Real Case %if (IS_UNIFORM) /* Generate real uniform random numbers */ *y++ = DSP_UniformRand(urandSeed) * (*pMax - *pMin) + *pMin; %else /* Generate real normal (gaussian) random numbers */ *y++ = DSP_NormalRand(urandSeed) * sqrt(*pVar) + *pMean; %endif %endif %endfunction %% DSP_CallRandomNumberGenerator %% Function: ================================================ %% Abstract: %% Determine if data is a non-scalar frame. %% Note that frameSize must be > 1 even when the input %% is continuous, e.g., could not be a frame. %% %function InputIsNonscalarFrame(frameSize, TID) void %return (LibIsDiscrete(TID) && frameSize > 1) %endfunction %% InputIsNonscalarFrame %% Function: ================================================ %% Abstract: %function DSP_ScalarUniformNumGen(IS_COMPLEX,OUTPORT_NUM) Output %% %assign minVal = LibBlockParameterValue(Min,0) %assign scale = LibBlockParameterValue(Max,0) - minVal /* Uniform: all scalar inputs */ %if (IS_COMPLEX) /* Generate complex uniform random numbers */ %% %if scale == 1 && minVal == 0 %% %.re = DSP_UniformRand((uint32_T *)%.re); %.im = DSP_UniformRand((uint32_T *)%.im); %% %elseif scale == 1 && minVal != 0 %% %.re = DSP_UniformRand((uint32_T *)%.re) + %;; %.im = DSP_UniformRand((uint32_T *)%.im) + %;; %% %elseif LibBlockParameterValue(Min,0) == 0 %% %.re = DSP_UniformRand((uint32_T *)%.re) * %; %.im = DSP_UniformRand((uint32_T *)%.im) * %; %else %.re = DSP_UniformRand((uint32_T *)%.re) * % + %; %.im = DSP_UniformRand((uint32_T *)%.im) * % + %; %endif %else %% Real Case /* Generate real uniform random numbers */ %if scale == 1 && minVal == 0 %% % = DSP_UniformRand((uint32_T *)%); %% %elseif scale == 1 && minVal != 0 %% % = DSP_UniformRand((uint32_T *)%) + %; %elseif LibBlockParameterValue(Min,0) == 0 %% % = DSP_UniformRand((uint32_T *)%) * %; %else % = DSP_UniformRand((uint32_T *)%) * % + %; %endif %endif %endfunction %% DSP_ScalarUniformNumGen %% Function: ================================================ %% Abstract: %function DSP_ScalarGaussianNumGen(IS_COMPLEX,OUTPORT_NUM) Output %% %assign varVal = LibBlockParameterValue(Variance,0) %% %if (IS_COMPLEX) /* Generate complex normal (gaussian) random numbers */ %% %assign isMeanComplex = CAST("Boolean",(Mean.ComplexSignal == "yes")) %assign meanVal_re = CAST("Number",LibBlockParameterValue(Mean,"%0")) %% %if varVal != 0 && varVal != 2 { real_T sqrt_var = sqrt(%/2); %endif %% %if (isMeanComplex) %% %assign meanVal_im = CAST("Number",LibBlockParameterValue(Mean,"%0")) %% %if varVal == 0 && meanVal_re != 0 && meanVal_im != 0 %% %.re = %; %.im = %; %% %elseif varVal == 2 && meanVal_re == 0 && meanVal_im != 0 %.re = DSP_NormalRand((uint32_T *)%.re); %.im = DSP_NormalRand((uint32_T *)%.im) + %; %% %elseif varVal == 2 && meanVal_re != 0 && meanVal_im != 0 %% %.re = DSP_NormalRand((uint32_T *)%.re) + %; %.im = DSP_NormalRand((uint32_T *)%.im) + %; %else %% %.re = DSP_NormalRand((uint32_T *)%.re) * sqrt_var + %; %.im = DSP_NormalRand((uint32_T *)%.im) * sqrt_var + %; %endif %% %else %% Output is Complex, Mean is not complex %% %if varVal == 0 && meanVal_re == 0 %% %.re = 0.0; %.im = 0.0; %% %elseif varVal == 0 && meanVal_re != 0 %% %.re = %; %.im = 0.0; %% %elseif varVal == 2 && meanVal_re == 0 %.re = DSP_NormalRand((uint32_T *)%.re); %.im = DSP_NormalRand((uint32_T *)%.im); %% %elseif varVal == 2 && meanVal_re != 0 %% /* start real mean variance = 2 */ %.re = DSP_NormalRand((uint32_T *)%.re) + %; %.im = DSP_NormalRand((uint32_T *)%.im); /* end real mean var = 2 */ %% %elseif meanVal_re == 0 && varVal != 0 %% %.re = DSP_NormalRand((uint32_T *)%) * sqrt_var; %.im = DSP_NormalRand((uint32_T *)%.im) * sqrt_var; %% %else %% %.re = DSP_NormalRand((uint32_T *)%0")>) * sqrt_var + %; %.im = DSP_NormalRand((uint32_T *)%0")>) * sqrt_var; %endif %endif %% %if varVal != 0 && varVal != 2 } %endif %else %% Real Case /* Generate real normal (gaussian) random numbers */ %% %assign meanVal = LibBlockParameterValue(Mean,0) %% %if varVal != 0 && varVal != 1 { real_T sqrt_var = sqrt(%); %endif %% %if varVal == 1 && meanVal == 0 % = DSP_NormalRand((uint32_T *)%); %% %elseif varVal == 0 % = %; %% %elseif varVal == 1 % = DSP_NormalRand((uint32_T *)%) + %; %% %elseif meanVal == 0 % = DSP_NormalRand((uint32_T *)%) * sqrt_var; %% %else % = DSP_NormalRand((uint32_T *)%) * sqrt_var + %; %endif %% %if varVal != 0 && varVal != 1 } %endif %endif %endfunction %% DSP_ScalarGaussianNumGen %% Function: SFcnIsDiscrete ================================================ %% Abstract: %% Determine if block is in Discrete Mode %% %function SFcnIsDiscrete() void %return (SFcnParamSettings.IsDiscrete == "Yes") %endfunction %% Function: Start ================================================ %% Abstract: %% Initialize the real and/or imag seeds for all channels. %% Compute the first random seed %% %function Start(block, system) Output /* DSP Blockset Random Source (%) - % */ /* Initialize the Random Seeds */ %assign OUTPORT_NUM = 0 %assign numDims = LibBlockOutputSignalNumDimensions(OUTPORT_NUM) %assign dims = LibBlockOutputSignalDimensions(OUTPORT_NUM) %assign nchans = (numDims == 2) ? dims[1] : 1 %assign frameSize = SFcnIsDiscrete() ? dims[0] : 1 %assign IS_COMPLEX = CAST("Boolean",(SFcnParamSettings.OutputType == "Complex")) %assign IS_SEED_TUNE = CAST("Boolean",(SFcnParamSettings.SeedIsTune == "Yes")) %assign multipleChans = (nchans > 1) %if multipleChans { %endif %if IS_SEED_TUNE %assign seedVal = InitSeed.Value %assign seedLen = LibGetNumberOfElements(seedVal) %else %assign seedLen = 1 %endif %% %% Determine datatype for the random seed: %% %assign urandDType = (IS_COMPLEX) ? "cuint32_T *" : "uint32_T *" %if multipleChans %urandSeed = (%)%; %endif %% %if !IS_SEED_TUNE && multipleChans real_T seedVal = %; %endif %% %\ %if multipleChans } %endif %endfunction %%%%%%%%%%%%%%%%%%%%% %% Function: Outputs ============================================================= %% %function Outputs(block, system) Output /* DSP Blockset Random Source (%) - % */ /* Create the Random Numbers */ %assign OUTPORT_NUM = 0 %assign IS_COMPLEX = CAST("Boolean",(SFcnParamSettings.OutputType == "Complex")) %assign IS_UNIFORM = CAST("Boolean",(SFcnParamSettings.SrcType == "Uniform")) %% %assign numDims = LibBlockOutputSignalNumDimensions(OUTPORT_NUM) %assign dims = LibBlockOutputSignalDimensions(OUTPORT_NUM) %assign nchans = (numDims == 2) ? dims[1] : 1 %assign frameSize = SFcnIsDiscrete() ? dims[0] : 1 %% %assign multipleChans = (nchans >1) %assign isScalar = (!multipleChans && frameSize == 1) %assign isUniformScalar = CAST("Boolean",0) %assign isGaussianScalar = CAST("Boolean",0) %% %% Determine datatype for the random seed: %assign urandDType = (IS_COMPLEX) ? "cuint32_T *" : "uint32_T *" %assign outDType = (IS_COMPLEX) ? "creal_T *" : "real_T *" %% %if (IS_UNIFORM) %assign maxVal = Max.Value %assign maxLen = LibGetNumberOfElements(maxVal) %assign minVal = Min.Value %assign minLen = LibGetNumberOfElements(minVal) %assign isUniformScalar = CAST("Boolean",(minLen == 1 && maxLen == 1 && isScalar)) %else %assign meanVal = Mean.Value %assign meanLen = LibGetNumberOfElements(meanVal) %assign varVal = Variance.Value %assign varLen = LibGetNumberOfElements(varVal) %assign isMeanComplex = CAST("Boolean",(Mean.ComplexSignal == "yes")) %assign meanDType = (isMeanComplex) ? "creal_T *" : "real_T *" %assign isGaussianScalar = CAST("Boolean",(meanLen == 1 && varLen == 1 && isScalar)) %endif %% %if isUniformScalar && nchans == 1 %\ %elseif isGaussianScalar && nchans == 1 %\ %else { %y = (%)%; %urandSeed = (%)%; %% %if (IS_UNIFORM) real_T *pMin = (real_T *)%; real_T *pMax = (real_T *)%; %else %pMean = (%)%; real_T *pVar = (real_T *)%; %endif %% %if multipleChans int_T i; for(i=0;i<%;i++) { %endif %if % int_T j; for(j=0;j<%;j++ ) { %endif %% %\ %% %if % } %endif %% %if multipleChans urandSeed++; %if (IS_UNIFORM) %if (maxLen > 1) pMax++; %endif %if (minLen > 1) pMin++; %endif %else %if (varLen > 1) pVar++; %endif %if (meanLen > 1) pMean++; %endif %endif } %endif } %endif %endfunction %% [EOF] sdsprandsrc.tlc