Exemplo n.º 1
0
Double GetRealScalar(pMatrix ppm, int element)
{
        rMatrix pm = ppm[element];

	if ((GetM(pm) == 1) && (GetN(pm) == 1)
	  && (IsNumeric(pm)) && (!IsComplex(pm)) ) {
		return(mxGetScalar(pm));
	} else {
		ErrMsgTxt("Expecting a scalar argument.");
	}
        return(0.0);
}
Exemplo n.º 2
0
/**	\brief MATLAB entry point.
 *
 *	This is the function that MATLAB actually calls when executing the included
 *	functions.  This function checks the validity of the inputs and outputs,
 *	and calls the actual worker function.
 *
 *	\param nlhs the number of expected output arguments.
 *	\param plhs place holders for the output arguments.
 *	\param nrhs the number of input arguments.
 *	\param prhs the actual input arguments.
 */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	if (nrhs < 2)
		mexErrMsgTxt("Too few arguments in MEXCALCESIG.\n");

	if (nrhs > 3)
		mexErrMsgTxt("Too many arguments in MEXCALCESIG.\n");

	if (nrhs < 0)
		mexErrMsgTxt("Too few arguments in MEXCALCESIG.\n");

	if (nlhs > 1)
		mexErrMsgTxt("Too many outputs in MEXCALCESIG.\n");
		
	TmexArray P(prhs[0]), G(prhs[1]);

	if (P.size() != G.size())
		mexErrMsgTxt("P and G must be the same size in MEXCALCESIG.\n");

	double size_mult = 1;

	if (nrhs > 2) {
		TmexArray S(prhs[2]);
		if (S.size() == 1) {
			size_mult = S[0];
		}
	}
	
	if(!IsComplex(P) && !IsComplex(G) )
		plhs[0] = mxCreateDoubleMatrix(static_cast<int>(P.size()),static_cast<int>(size_mult*P.size()),mxREAL);
	else
		plhs[0] = mxCreateDoubleMatrix(static_cast<int>(P.size()),static_cast<int>(size_mult*P.size()),mxCOMPLEX);
	
	TmexArray Esig(plhs[0]);
		
	CalcEsig(Esig, P, G);
}
Exemplo n.º 3
0
BOOL CXaraFileRectangle::WriteRectangle(BaseCamelotFilter * pFilter, NodeRegularShape * pShape)
{
	BOOL ok;

	// we need to determine how is rectangle has been altered, i.e. rotated, rounded, stellated
	// or reformed. using this information we jump to one of the following functions to write
	// the information out for us.

	const INT32 REFORMED	= 0x1;
	const INT32 STELLATED	= 0x2;
	const INT32 ROUNDED	= 0x4;
	const INT32 COMPLEX	= 0x8;

	INT32 RectangleType = 0;

	if (IsReformed(pShape)) RectangleType |= REFORMED;
	if (IsStellated(pShape)) RectangleType |= STELLATED;
	if (IsRounded(pShape)) RectangleType |= ROUNDED;
	if (IsComplex(pShape)) RectangleType |= COMPLEX;

	switch (RectangleType)
	{
		case 0									: ok = WriteRectangleSimple(pFilter, pShape); break;
		case REFORMED							: ok = WriteRectangleSimpleReformed(pFilter, pShape); break;
		case STELLATED							: ok = WriteRectangleSimpleStellated(pFilter, pShape); break;
		case STELLATED|REFORMED					: ok = WriteRectangleSimpleStellatedReformed(pFilter, pShape); break;
		case ROUNDED							: ok = WriteRectangleSimpleRounded(pFilter, pShape); break;
		case ROUNDED|REFORMED					: ok = WriteRectangleSimpleRoundedReformed(pFilter, pShape); break;
		case ROUNDED|STELLATED					: ok = WriteRectangleSimpleRoundedStellated(pFilter, pShape); break;
		case ROUNDED|STELLATED|REFORMED			: ok = WriteRectangleSimpleRoundedStellatedReformed(pFilter, pShape); break;
		case COMPLEX							: ok = WriteRectangleComplex(pFilter, pShape); break;
		case COMPLEX|REFORMED					: ok = WriteRectangleComplexReformed(pFilter, pShape); break;
		case COMPLEX|STELLATED					: ok = WriteRectangleComplexStellated(pFilter, pShape); break;
		case COMPLEX|STELLATED|REFORMED			: ok = WriteRectangleComplexStellatedReformed(pFilter, pShape); break;
		case COMPLEX|ROUNDED					: ok = WriteRectangleComplexRounded(pFilter, pShape); break;
		case COMPLEX|ROUNDED|REFORMED			: ok = WriteRectangleComplexRoundedReformed(pFilter, pShape); break;
		case COMPLEX|ROUNDED|STELLATED			: ok = WriteRectangleComplexRoundedStellated(pFilter, pShape); break;
		case COMPLEX|ROUNDED|STELLATED|REFORMED	: ok = WriteRectangleComplexRoundedStellatedReformed(pFilter, pShape); break;
		default									: ok = WriteShapeInvalid(pFilter, pShape); break;
	}

	return ok;
}
Exemplo n.º 4
0
void WSMSGridder::Predict(double* real, double* imaginary)
{
	if(imaginary==0 && IsComplex())
		throw std::runtime_error("Missing imaginary in complex prediction");
	if(imaginary!=0 && !IsComplex())
		throw std::runtime_error("Imaginary specified in non-complex prediction");
	
	MSData* msDataVector = new MSData[MeasurementSetCount()];
	_hasFrequencies = false;
	for(size_t i=0; i!=MeasurementSetCount(); ++i)
		initializeMeasurementSet(i, msDataVector[i]);
	
	double minW = msDataVector[0].minW;
	double maxW = msDataVector[0].maxW;
	for(size_t i=1; i!=MeasurementSetCount(); ++i)
	{
		if(msDataVector[i].minW < minW) minW = msDataVector[i].minW;
		if(msDataVector[i].maxW > maxW) maxW = msDataVector[i].maxW;
	}
	
	_gridder = std::unique_ptr<WStackingGridder>(new WStackingGridder(_actualInversionWidth, _actualInversionHeight, _actualPixelSizeX, _actualPixelSizeY, _cpuCount, _imageBufferAllocator, AntialiasingKernelSize(), OverSamplingFactor()));
	_gridder->SetGridMode(_gridMode);
	if(_denormalPhaseCentre)
		_gridder->SetDenormalPhaseCentre(_phaseCentreDL, _phaseCentreDM);
	_gridder->SetIsComplex(IsComplex());
	//_imager->SetImageConjugatePart(Polarization() == Polarization::YX && IsComplex());
	_gridder->PrepareWLayers(WGridSize(), double(_memSize)*(7.0/10.0), minW, maxW);
	
	if(Verbose())
	{
		for(size_t i=0; i!=MeasurementSetCount(); ++i)
			countSamplesPerLayer(msDataVector[i]);
	}
	
	double *resizedReal = 0, *resizedImag = 0;
	if(ImageWidth()!=_actualInversionWidth || ImageHeight()!=_actualInversionHeight)
	{
		FFTResampler resampler(ImageWidth(), ImageHeight(), _actualInversionWidth, _actualInversionHeight, _cpuCount);
		
		if(imaginary == 0)
		{
			resizedReal = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight());
			resampler.RunSingle(real, resizedReal);
			real = resizedReal;
		}
		else {
			resizedReal = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight());
			resizedImag = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight());
			resampler.Start();
			resampler.AddTask(real, resizedReal);
			resampler.AddTask(imaginary, resizedImag);
			resampler.Finish();
			real = resizedReal;
			imaginary = resizedImag;
		}
	}
	
	for(size_t pass=0; pass!=_gridder->NPasses(); ++pass)
	{
		std::cout << "Fourier transforms for pass " << pass << "... ";
		if(Verbose()) std::cout << '\n';
		else std::cout << std::flush;
		if(imaginary == 0)
			_gridder->InitializePrediction(real);
		else
			_gridder->InitializePrediction(real, imaginary);
		
		_gridder->StartPredictionPass(pass);
		
		std::cout << "Predicting...\n";
		for(size_t i=0; i!=MeasurementSetCount(); ++i)
			predictMeasurementSet(msDataVector[i]);
	}
	
	if(ImageWidth()!=_actualInversionWidth || ImageHeight()!=_actualInversionHeight)
	{
		_imageBufferAllocator->Free(resizedReal);
		_imageBufferAllocator->Free(resizedImag);
	}
	
	size_t totalRowsWritten = 0, totalMatchingRows = 0;
	for(size_t i=0; i!=MeasurementSetCount(); ++i)
	{
		totalRowsWritten += msDataVector[i].totalRowsProcessed;
		totalMatchingRows += msDataVector[i].matchingRows;
	}
	
	std::cout << "Total rows written: " << totalRowsWritten;
	if(totalMatchingRows != 0)
		std::cout << " (overhead: " << std::max(0.0, round(totalRowsWritten * 100.0 / totalMatchingRows - 100.0)) << "%)";
	std::cout << '\n';
	delete[] msDataVector;
}
Exemplo n.º 5
0
void WSMSGridder::initializeMeasurementSet(size_t msIndex, WSMSGridder::MSData& msData)
{
	MSProvider& msProvider = MeasurementSet(msIndex);
	msData.msProvider = &msProvider;
	casacore::MeasurementSet& ms(msProvider.MS());
	if(ms.nrow() == 0) throw std::runtime_error("Table has no rows (no data)");
	
	/**
		* Read some meta data from the measurement set
		*/
	casacore::MSAntenna aTable = ms.antenna();
	size_t antennaCount = aTable.nrow();
	if(antennaCount == 0) throw std::runtime_error("No antennae in set");
	casacore::MPosition::ROScalarColumn antPosColumn(aTable, aTable.columnName(casacore::MSAntennaEnums::POSITION));
	casacore::MPosition ant1Pos = antPosColumn(0);
	
	msData.bandData = MultiBandData(ms.spectralWindow(), ms.dataDescription());
	if(Selection(msIndex).HasChannelRange())
	{
		msData.startChannel = Selection(msIndex).ChannelRangeStart();
		msData.endChannel = Selection(msIndex).ChannelRangeEnd();
		std::cout << "Selected channels: " << msData.startChannel << '-' << msData.endChannel << '\n';
		const BandData& firstBand = msData.bandData.FirstBand();
		if(msData.startChannel >= firstBand.ChannelCount() || msData.endChannel > firstBand.ChannelCount()
			|| msData.startChannel == msData.endChannel)
		{
			std::ostringstream str;
			str << "An invalid channel range was specified! Measurement set only has " << firstBand.ChannelCount() << " channels, requested imaging range is " << msData.startChannel << " -- " << msData.endChannel << '.';
			throw std::runtime_error(str.str());
		}
	}
	else {
		msData.startChannel = 0;
		msData.endChannel = msData.bandData.FirstBand().ChannelCount();
	}
	casacore::MEpoch::ROScalarColumn timeColumn(ms, ms.columnName(casacore::MSMainEnums::TIME));
	const MultiBandData selectedBand = msData.SelectedBand();
	if(_hasFrequencies)
	{
		_freqLow = std::min(_freqLow, selectedBand.LowestFrequency());
		_freqHigh = std::max(_freqHigh, selectedBand.HighestFrequency());
		_bandStart = std::min(_bandStart, selectedBand.BandStart());
		_bandEnd = std::max(_bandEnd, selectedBand.BandEnd());
		_startTime = std::min(_startTime, msProvider.StartTime());
	} else {
		_freqLow = selectedBand.LowestFrequency();
		_freqHigh = selectedBand.HighestFrequency();
		_bandStart = selectedBand.BandStart();
		_bandEnd = selectedBand.BandEnd();
		_startTime = msProvider.StartTime();
		_hasFrequencies = true;
	}
	
	casacore::MSField fTable(ms.field());
	casacore::MDirection::ROScalarColumn phaseDirColumn(fTable, fTable.columnName(casacore::MSFieldEnums::PHASE_DIR));
	casacore::MDirection phaseDir = phaseDirColumn(Selection(msIndex).FieldId());
	casacore::MEpoch curtime = timeColumn(0);
	casacore::MeasFrame frame(ant1Pos, curtime);
	casacore::MDirection::Ref j2000Ref(casacore::MDirection::J2000, frame);
	casacore::MDirection j2000 = casacore::MDirection::Convert(phaseDir, j2000Ref)();
	casacore::Vector<casacore::Double> j2000Val = j2000.getValue().get();
	_phaseCentreRA = j2000Val[0];
	_phaseCentreDec = j2000Val[1];
	if(fTable.keywordSet().isDefined("WSCLEAN_DL"))
		_phaseCentreDL = fTable.keywordSet().asDouble(casacore::RecordFieldId("WSCLEAN_DL"));
	else _phaseCentreDL = 0.0;
	if(fTable.keywordSet().isDefined("WSCLEAN_DM"))
		_phaseCentreDM = fTable.keywordSet().asDouble(casacore::RecordFieldId("WSCLEAN_DM"));
	else _phaseCentreDM = 0.0;

	_denormalPhaseCentre = _phaseCentreDL != 0.0 || _phaseCentreDM != 0.0;
	if(_denormalPhaseCentre)
		std::cout << "Set has denormal phase centre: dl=" << _phaseCentreDL << ", dm=" << _phaseCentreDM << '\n';
	
	std::cout << "Determining min and max w & theoretical beam size... " << std::flush;
	msData.maxW = 0.0;
	msData.minW = 1e100;
	double maxBaseline = 0.0;
	std::vector<float> weightArray(selectedBand.MaxChannels());
	msProvider.Reset();
	while(msProvider.CurrentRowAvailable())
	{
		size_t dataDescId;
		double uInM, vInM, wInM;
		msProvider.ReadMeta(uInM, vInM, wInM, dataDescId);
		const BandData& curBand = selectedBand[dataDescId];
		double wHi = fabs(wInM / curBand.SmallestWavelength());
		double wLo = fabs(wInM / curBand.LongestWavelength());
		double baselineInM = sqrt(uInM*uInM + vInM*vInM + wInM*wInM);
		double halfWidth = 0.5*ImageWidth(), halfHeight = 0.5*ImageHeight();
		if(wHi > msData.maxW || wLo < msData.minW || baselineInM / curBand.SmallestWavelength() > maxBaseline)
		{
			msProvider.ReadWeights(weightArray.data());
			const float* weightPtr = weightArray.data();
			for(size_t ch=0; ch!=curBand.ChannelCount(); ++ch)
			{
				if(*weightPtr != 0.0)
				{
					const double wavelength = curBand.ChannelWavelength(ch);
					double
						uInL = uInM/wavelength, vInL = vInM/wavelength,
						wInL = wInM/wavelength,
						x = uInL * PixelSizeX() * ImageWidth(),
						y = vInL * PixelSizeY() * ImageHeight(),
						imagingWeight = this->PrecalculatedWeightInfo()->GetWeight(uInL, vInL);
					if(imagingWeight != 0.0)
					{
						if(floor(x) > -halfWidth  && ceil(x) < halfWidth &&
							floor(y) > -halfHeight && ceil(y) < halfHeight)
						{
							msData.maxW = std::max(msData.maxW, fabs(wInL));
							msData.minW = std::min(msData.minW, fabs(wInL));
							maxBaseline = std::max(maxBaseline, baselineInM / wavelength);
						}
					}
				}
				++weightPtr;
			}
		}
		
		msProvider.NextRow();
	}
	if(msData.minW == 1e100)
	{
		msData.minW = 0.0;
		msData.maxW = 0.0;
	}
	_beamSize = 1.0 / maxBaseline;
	std::cout << "DONE (w=[" << msData.minW << ":" << msData.maxW << "] lambdas, maxuvw=" << maxBaseline << " lambda, beam=" << Angle::ToNiceString(_beamSize) << ")\n";
	if(HasWLimit()) {
		msData.maxW *= (1.0 - WLimit());
		if(msData.maxW < msData.minW) msData.maxW = msData.minW;
	}

	_actualInversionWidth = ImageWidth();
	_actualInversionHeight = ImageHeight();
	_actualPixelSizeX = PixelSizeX();
	_actualPixelSizeY = PixelSizeY();
	
	if(SmallInversion())
	{
		double totalWidth = _actualInversionWidth * _actualPixelSizeX, totalHeight = _actualInversionHeight * _actualPixelSizeY;
		// Calc min res based on Nyquist sampling rate
		size_t minResX = size_t(ceil(totalWidth*2 / _beamSize));
		if(minResX%4 != 0) minResX += 4 - (minResX%4);
		size_t minResY = size_t(ceil(totalHeight*2 / _beamSize));
		if(minResY%4 != 0) minResY += 4 - (minResY%4);
		if(minResX < _actualInversionWidth || minResY < _actualInversionHeight)
		{
			_actualInversionWidth = std::max(std::min(minResX, _actualInversionWidth), size_t(32));
			_actualInversionHeight = std::max(std::min(minResY, _actualInversionHeight), size_t(32));
			std::cout << "Setting small inversion image size of " << _actualInversionWidth << " x " << _actualInversionHeight << "\n";
			_actualPixelSizeX = totalWidth / _actualInversionWidth;
			_actualPixelSizeY = totalHeight / _actualInversionHeight;
		}
		else {
			std::cout << "Small inversion enabled, but inversion resolution already smaller than beam size: not using optimization.\n";
		}
	}
	
	if(Verbose() || !HasWGridSize())
	{
		double
			maxL = ImageWidth() * PixelSizeX() * 0.5 + fabs(_phaseCentreDL),
			maxM = ImageHeight() * PixelSizeY() * 0.5 + fabs(_phaseCentreDM),
			lmSq = maxL * maxL + maxM * maxM;
		double cMinW = IsComplex() ? -msData.maxW : msData.minW;
		double radiansForAllLayers;
		if(lmSq < 1.0)
			radiansForAllLayers = 2 * M_PI * (msData.maxW - cMinW) * (1.0 - sqrt(1.0 - lmSq));
		else
			radiansForAllLayers = 2 * M_PI * (msData.maxW - cMinW);
		size_t suggestedGridSize = size_t(ceil(radiansForAllLayers));
		if(suggestedGridSize == 0) suggestedGridSize = 1;
		if(suggestedGridSize < _cpuCount)
		{
			// When nwlayers is lower than the nr of cores, we cannot parallellize well. 
			// However, we don't want extra w-layers if we are low on mem, as that might slow down the process
			double memoryRequired = double(_cpuCount) * double(sizeof(double))*double(_actualInversionWidth*_actualInversionHeight);
			if(4.0 * memoryRequired < double(_memSize))
			{
				std::cout <<
					"The theoretically suggested number of w-layers (" << suggestedGridSize << ") is less than the number of availables\n"
					"cores (" << _cpuCount << "). Changing suggested number of w-layers to " << _cpuCount << ".\n";
				suggestedGridSize = _cpuCount;
			}
			else {
				std::cout <<
					"The theoretically suggested number of w-layers (" << suggestedGridSize << ") is less than the number of availables\n"
					"cores (" << _cpuCount << "), but there is not enough memory available to increase the number of w-layers.\n"
					"Not all cores can be used efficiently.\n";
			}
		}
		if(Verbose())
			std::cout << "Suggested number of w-layers: " << ceil(suggestedGridSize) << '\n';
		if(!HasWGridSize())
			SetWGridSize(suggestedGridSize);
	}
}
Exemplo n.º 6
0
void WSMSGridder::Invert()
{
	MSData* msDataVector = new MSData[MeasurementSetCount()];
	_hasFrequencies = false;
	for(size_t i=0; i!=MeasurementSetCount(); ++i)
		initializeMeasurementSet(i, msDataVector[i]);
	
	double minW = msDataVector[0].minW;
	double maxW = msDataVector[0].maxW;
	for(size_t i=1; i!=MeasurementSetCount(); ++i)
	{
		if(msDataVector[i].minW < minW) minW = msDataVector[i].minW;
		if(msDataVector[i].maxW > maxW) maxW = msDataVector[i].maxW;
	}
	
	_gridder = std::unique_ptr<WStackingGridder>(new WStackingGridder(_actualInversionWidth, _actualInversionHeight, _actualPixelSizeX, _actualPixelSizeY, _cpuCount, _imageBufferAllocator, AntialiasingKernelSize(), OverSamplingFactor()));
	_gridder->SetGridMode(_gridMode);
	if(_denormalPhaseCentre)
		_gridder->SetDenormalPhaseCentre(_phaseCentreDL, _phaseCentreDM);
	_gridder->SetIsComplex(IsComplex());
	//_imager->SetImageConjugatePart(Polarization() == Polarization::YX && IsComplex());
	_gridder->PrepareWLayers(WGridSize(), double(_memSize)*(7.0/10.0), minW, maxW);
	
	if(Verbose())
	{
		for(size_t i=0; i!=MeasurementSetCount(); ++i)
			countSamplesPerLayer(msDataVector[i]);
	}
	
	_totalWeight = 0.0;
	for(size_t pass=0; pass!=_gridder->NPasses(); ++pass)
	{
		std::cout << "Gridding pass " << pass << "... ";
		if(Verbose()) std::cout << '\n';
		else std::cout << std::flush;
		_inversionWorkLane.reset(new ao::lane<InversionWorkItem>(2048));
		
		_gridder->StartInversionPass(pass);
		
		for(size_t i=0; i!=MeasurementSetCount(); ++i)
		{
			_inversionWorkLane->clear();
			
			MSData& msData = msDataVector[i];
			
			const MultiBandData selectedBand(msData.SelectedBand());
			
			boost::thread thread(&WSMSGridder::workThreadParallel, this, &selectedBand);
		
			gridMeasurementSet(msData);
			
			_inversionWorkLane->write_end();
			thread.join();
		}
		_inversionWorkLane.reset();
		
		std::cout << "Fourier transforms...\n";
		_gridder->FinishInversionPass();
	}
	
	if(Verbose())
	{
		size_t totalRowsRead = 0, totalMatchingRows = 0;
		for(size_t i=0; i!=MeasurementSetCount(); ++i)
		{
			totalRowsRead += msDataVector[i].totalRowsProcessed;
			totalMatchingRows += msDataVector[i].matchingRows;
		}
		
		std::cout << "Total rows read: " << totalRowsRead;
		if(totalMatchingRows != 0)
			std::cout << " (overhead: " << std::max(0.0, round(totalRowsRead * 100.0 / totalMatchingRows - 100.0)) << "%)";
		std::cout << '\n';
	}
	
	if(NormalizeForWeighting())
		_gridder->FinalizeImage(1.0/_totalWeight, false);
	else {
		std::cout << "Not dividing by normalization factor of " << _totalWeight << ".\n";
		_gridder->FinalizeImage(1.0, true);
	}
	
	if(ImageWidth()!=_actualInversionWidth || ImageHeight()!=_actualInversionHeight)
	{
		FFTResampler resampler(_actualInversionWidth, _actualInversionHeight, ImageWidth(), ImageHeight(), _cpuCount);
		
		if(IsComplex())
		{
			double *resizedReal = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight());
			double *resizedImag = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight());
			resampler.Start();
			resampler.AddTask(_gridder->RealImage(), resizedReal);
			resampler.AddTask(_gridder->ImaginaryImage(), resizedImag);
			resampler.Finish();
			_gridder->ReplaceRealImageBuffer(resizedReal);
			_gridder->ReplaceImaginaryImageBuffer(resizedImag);
		}
		else {
			double *resized = _imageBufferAllocator->Allocate(ImageWidth() * ImageHeight());
			resampler.RunSingle(_gridder->RealImage(), resized);
			_gridder->ReplaceRealImageBuffer(resized);
		}
	}
	
	delete[] msDataVector;
}
Exemplo n.º 7
0
int GetRealSparseVector(pMatrix ppm, int element, Double *vec, int *index, int start, int len, int col)
{
	int	j, k, k1, m, n, start1, count = 0;
	int	*ir, *jc;
	double	*pr, *pr0;
        rMatrix pm = ppm[element];

	m = GetM(pm);
	n = GetN(pm);

	if (  ((col == 0) && (((m != 1) && (n != 1)) || ((m == 1) && (n > len)) || ((n == 1) && (m > len)))) ||
              ((col != 0) && ((m > len) || (col > n))) ||
	      !IsNumeric(pm) ||
              IsComplex(pm)  ) {
		ErrMsgTxt("invalid vector.");
	}

	pr = GetPr(pm);

	if (!IsSparse(pm)) {
                if ((((n == 1) || (col != 0)) && (m != len)) || ((col == 0) && (m == 1) && (n != len)))
                        ErrMsgTxt("invalid vector.");

                if (col)
                	pr += (col - 1) * m;
                for (k = 0; k < len; k++, pr++) {
                        if (*pr) {
				*(vec++) = *pr;
                        	*(index++) = start + k;
                        	count++;
                        }
		}
	} else if (IsSparse(pm)) {
                int j1, j2;

		jc = mxGetJc(pm);
		ir = mxGetIr(pm);
                pr0 = pr;
                if (col == 0) {
                        j1 = 0;
                        j2 = n;
                }
                else {
                        j1 = col - 1;
                        j2 = col;
                }
		for (j = j1; j < j2; j++) {
                        k = jc[j];
                        k1 = jc[j + 1];
                        pr = pr0 + k;
                        start1 = start;
                        if (col == 0)
                        	start1 += j * m;
                        for (; k < k1; k++, pr++, vec++, index++) {
                                *vec = *pr;
                                *index = start1 + ir[k];
                                count++;
			}
		}
	} else {
		ErrMsgTxt("Can't figure out this matrix.");
	}

        return(count);
}