void SceneValidator::ValidateTexture(Texture *texture, const FilePath &texturePathname, const String &validatedObjectName, Set<String> &errorsLog)
{
	if(!texture) return;
	
	String path = texturePathname.GetRelativePathname(pathForChecking);
	String textureInfo = path + " for object: " + validatedObjectName;

	if(texture->IsPinkPlaceholder())
	{
		errorsLog.insert("Can't load texture: " + textureInfo);
	}

	bool pathIsCorrect = ValidatePathname(texturePathname, validatedObjectName);
	if(!pathIsCorrect)
	{
		errorsLog.insert("Wrong path of: " + textureInfo);
	}
	
	if(!IsPowerOf2(texture->GetWidth()) || !IsPowerOf2(texture->GetHeight()))
	{
		errorsLog.insert("Wrong size of " + textureInfo);
	}
    
    if(texture->GetWidth() > 2048 || texture->GetHeight() > 2048)
	{
		errorsLog.insert("Texture is too big. " + textureInfo);
	}
}
TrackArray::TrackArray( int width, int height, int cellSize ):
    TrackDataContainer( width, height, cellSize )
{
    // zapewnia, iz zarowno szerokosc, jak i wysokosc, sa potegami dwojki
    if( !IsPowerOf2(width) || !IsPowerOf2(height) )
        throw TrackContainerException();

    mpDataMatrix = allocateArray( width, height, cellSize, mCellSizeLogarithm );
}
Esempio n. 3
0
TEST(Pow2, Basics) {
  for (int i = 0; i < 32; ++i) {
    uint32_t ui = 1u << i;
    EXPECT_EQ(true, IsPowerOf2(ui));
    if (ui > 1) {
      EXPECT_EQ(false, IsPowerOf2(ui+1));
    }
    if (ui > 2) {
      EXPECT_EQ(false, IsPowerOf2(ui-1));
    }
  }
}
Esempio n. 4
0
bool GLTexture::Init( const std::string &name, int textureUnit ) {
    byte *pic, *picCopy;
    GLuint texture;
    int width, height, format;

    format = GL_RGBA;

    if ( EndsWith( name, ".tga" ) ) {
        pic = R_LoadTGA( name, width, height, format );
    } else {
        msg_warning( "no image file with name `%s' found\n", name.c_str() );
        return false;
    }

    if ( !IsPowerOf2( width ) || !IsPowerOf2( height ) ) {
        msg_warning0( "texture must have size in power of two\n" );
        return false;
    }

    picCopy = (byte *)malloc( width * height * 4 );

    _CH(glActiveTexture( GL_TEXTURE0 + textureUnit ));
    _CH(glGenTextures( 1, &texture ));
    _CH(glBindTexture( GL_TEXTURE_2D, texture ));
    _CH(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
    _CH(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));

    int mipmap = 0;
    while ( width > 1 || height > 1 ) {
        _CH(glTexImage2D( GL_TEXTURE_2D,
            mipmap,
            format,
            width,
            height,
            0,
            format,
            GL_UNSIGNED_BYTE,
            pic));

        int oldWidth, oldHeight;

        oldWidth = width;
        oldHeight = height;

        if ( width > 1 ) {
            width >>= 1;
        }

        if ( height > 1 ) {
            height >>= 1;
        }
Esempio n. 5
0
int validate_pe(void *raw, size_t raw_size, int is_exec)
{
    PIMAGE_DOS_HEADER     dos;
    PIMAGE_NT_HEADERS32   nt;

    dos = (PIMAGE_DOS_HEADER)raw;

    if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
        return 0;

    if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
        return 0;

    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);

    if( (uint32_t)nt < (uint32_t)raw)
        return 0;

    if(nt->Signature != IMAGE_NT_SIGNATURE)
        return 0;

    if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
        return 0;

    if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
        return 0;

    if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
        return 0;

    if( is_exec && nt->OptionalHeader.ImageBase != 0)
        return 0;

    if(nt->OptionalHeader.SectionAlignment < 4096)
    {
        if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
            return 0;
    }
    else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
        return 0;

    if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
       !IsPowerOf2(nt->OptionalHeader.FileAlignment))
        return 0;

    if(nt->FileHeader.NumberOfSections > 96)
        return 0;

    return 1;
}
Esempio n. 6
0
File: Crc.cpp Progetto: lcs2/carpg
inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
{
	if (IsPowerOf2(m))
		return n - ModPowerOf2(n, m);
	else
		return n - n%m;
}
Esempio n. 7
0
// ZeroTwoSequenceSampler Method Definitions
ZeroTwoSequenceSampler::ZeroTwoSequenceSampler(int64_t samplesPerPixel,
                                               int nSampledDimensions)
    : PixelSampler(RoundUpPow2(samplesPerPixel), nSampledDimensions) {
    if (!IsPowerOf2(samplesPerPixel))
        Warning(
            "Pixel samples being rounded up to power of 2 "
            "(from %" PRId64 " to %" PRId64 ").",
            samplesPerPixel, RoundUpPow2(samplesPerPixel));
}
bool SceneValidator::ValidateHeightmapPathname(const FilePath &pathForValidation, Set<String> &errorsLog)
{
	DVASSERT_MSG(!pathForChecking.IsEmpty(), "Need to set pathname for DataSource folder");

	bool pathIsCorrect = IsPathCorrectForProject(pathForValidation);
	if(pathIsCorrect)
	{
		String::size_type posPng = pathForValidation.GetAbsolutePathname().find(".png");
		String::size_type posHeightmap = pathForValidation.GetAbsolutePathname().find(Heightmap::FileExtension());
        
        pathIsCorrect = ((String::npos != posPng) || (String::npos != posHeightmap));
        if(!pathIsCorrect)
        {
            errorsLog.insert(Format("Heightmap path %s is wrong", pathForValidation.GetAbsolutePathname().c_str()));
            return false;
        }
        
        Heightmap *heightmap = new Heightmap();
        if(String::npos != posPng)
        {
            Image *image = CreateTopLevelImage(pathForValidation);
            pathIsCorrect = heightmap->BuildFromImage(image);
            SafeRelease(image);
        }
        else
        {
            pathIsCorrect = heightmap->Load(pathForValidation);
        }

        
        if(!pathIsCorrect)
        {
            SafeRelease(heightmap);
            errorsLog.insert(Format("Can't load Heightmap from path %s", pathForValidation.GetAbsolutePathname().c_str()));
            return false;
        }
        
        
        pathIsCorrect = IsPowerOf2(heightmap->Size() - 1);
        if(!pathIsCorrect)
        {
            errorsLog.insert(Format("Heightmap %s has wrong size", pathForValidation.GetAbsolutePathname().c_str()));
        }
        
        SafeRelease(heightmap);
		return pathIsCorrect;
	}
	else
	{
		errorsLog.insert(Format("Path %s is incorrect for project %s", pathForValidation.GetAbsolutePathname().c_str(), pathForChecking.GetAbsolutePathname().c_str()));
	}

	return pathIsCorrect;
}
Esempio n. 9
0
// AdaptiveSampler Method Definitions
AdaptiveSampler::AdaptiveSampler(int xstart, int xend,
                     int ystart, int yend, int mins, int maxs, const string &m,
                     float sopen, float sclose)
    : Sampler(xstart, xend, ystart, yend, RoundUpPow2(maxSamples),
              sopen, sclose) {
    xPos = xPixelStart;
    yPos = yPixelStart;
    supersamplePixel = false;
    if (mins > maxs) std::swap(mins, maxs);

    if (!IsPowerOf2(mins)) {
        Warning("Minimum pixel samples being rounded up to power of 2");
        minSamples = RoundUpPow2(mins);
    }
    else
        minSamples = mins;
    if (!IsPowerOf2(maxs)) {
        Warning("Maximum pixel samples being rounded up to power of 2");
        maxSamples = RoundUpPow2(maxs);
    }
    else
        maxSamples = maxs;

    if (minSamples < 2) {
        Warning("Adaptive sampler needs at least two initial pixel samples.  Using two.");
        minSamples = 2;
    }
    if (minSamples == maxSamples) {
        maxSamples *= 2;
        Warning("Adaptive sampler must have more maximum samples than minimum.  Using %d - %d",
                minSamples, maxSamples);
    }
    if (m == "contrast") method = ADAPTIVE_CONTRAST_THRESHOLD;
    else if (m == "shapeid") method = ADAPTIVE_COMPARE_SHAPE_ID;
    else {
        Warning("Adaptive sampling metric \"%s\" unknown.  Using \"contrast\".",
                m.c_str());
        method = ADAPTIVE_CONTRAST_THRESHOLD;
    }
    sampleBuf = NULL;
}
Esempio n. 10
0
// LDSampler Method Definitions
LDSampler::LDSampler(int xstart, int xend, int ystart, int yend, int ps,
                     float sopen, float sclose)
    : Sampler(xstart, xend, ystart, yend, RoundUpPow2(ps), sopen, sclose) {
    xPos = xPixelStart;
    yPos = yPixelStart;
    if (!IsPowerOf2(ps)) {
        Warning("Pixel samples being rounded up to power of 2");
        nPixelSamples = RoundUpPow2(ps);
    } else
        nPixelSamples = ps;
    sampleBuf = NULL;
}
Esempio n. 11
0
ezInt32 ezMath::PowerOfTwo_Ceil(ezUInt32 npot)
{
  if (IsPowerOf2 (npot))
    return (npot);

  for (int i=1; i <= (sizeof (npot) * 8); ++i)
  {
    npot >>= 1;

    if (npot == 1)
      return (npot << (i + 1));
  }

  return (1);
}
Esempio n. 12
0
ezInt32 ezMath::PowerOfTwo_Floor(ezUInt32 npot)
{
  if (IsPowerOf2 (npot))
    return (npot);

  for (ezInt32 i = 1; i <= (sizeof (npot) * 8); ++i)
  {
    npot >>= 1;

    if (npot == 1)
      return (npot << i);
  }

  return (1);
}
bool CubeMapTextureBrowser::ValidateTextureAndFillThumbnails(DAVA::FilePath& fp,
									  DAVA::Vector<QImage*>& icons,
									  DAVA::Vector<QSize>& actualSize)
{
	bool result = true;
	
	int width = 0;
	int height = 0;
	DAVA::Vector<DAVA::String> faceNames;
	CubemapUtils::GenerateFaceNames(fp.GetAbsolutePathname(), faceNames);
	for(size_t i = 0; i < faceNames.size(); ++i)
	{
		QImage faceImage;
		if(!faceImage.load(faceNames[i].c_str())) //file must be present
		{
			result = false;
		}
	
		if(faceImage.width() != faceImage.height() || //file must be square and be power of 2
		   !IsPowerOf2(faceImage.width()))
		{
			result = false;
		}
				
		if(0 == i)
		{
			width = faceImage.width();
			height = faceImage.height();
		}
		else if(faceImage.width() != width || //all files should be the same size
				faceImage.height() != height)
		{
			result = false;
		}
		
		//scale image and put scaled version to an array
		QImage scaledFaceTemp = faceImage.scaled(FACE_IMAGE_SIZE, FACE_IMAGE_SIZE);
		QImage* scaledFace = new QImage(scaledFaceTemp);
		
		icons.push_back(scaledFace);
		actualSize.push_back(QSize(faceImage.width(), faceImage.height()));
	}
	
	return result;
}
Esempio n. 14
0
	void AddPrimitive(MailboxPrim *prim) {
		if (nPrimitives == 1) {
			// Allocate initial _primitives_ array in voxel
			MailboxPrim **p = new MailboxPrim *[2];
			p[0] = onePrimitive;
			primitives = p;
		}
		else if (IsPowerOf2(nPrimitives)) {
			// Increase size of _primitives_ array in voxel
			int nAlloc = 2 * nPrimitives;
			MailboxPrim **p = new MailboxPrim *[nAlloc];
			for (u_int i = 0; i < nPrimitives; ++i)
				p[i] = primitives[i];
			delete[] primitives;
			primitives = p;
		}
		primitives[nPrimitives] = prim;
		++nPrimitives;
	}
Esempio n. 15
0
// LDSampler Method Definitions
LDSampler::LDSampler(int xstart, int xend,
		int ystart, int yend, int ps)
	: Sampler(xstart, xend, ystart, yend, RoundUpPow2(ps)) {
	xPos = xPixelStart - 1;
	yPos = yPixelStart;
	if (!IsPowerOf2(ps)) {
		Warning("Pixel samples being"
		        " rounded up to power of 2");
		pixelSamples = RoundUpPow2(ps);
	}
	else
		pixelSamples = ps;
	samplePos = pixelSamples;
	oneDSamples = twoDSamples = NULL;
	imageSamples = new float[5*pixelSamples];
	lensSamples = imageSamples + 2*pixelSamples;
	timeSamples = imageSamples + 4*pixelSamples;
	n1D = n2D = 0;
}
/**
    Open the device and do some initalisation work.
    
    @param  aParams device parameters
    @return Epoc error code, KErrNone if everything is OK
*/
TInt CWinVolumeDevice::Connect(const TMediaDeviceParams& aParams)
{
    
    __PRINT(_L("#-- CWinVolumeDevice::Connect()"));    
    
    if(!aParams.ipDevName)
    {
        __LOG(_L("#-- CWinVolumeDevice::Connect() device name is not set!"));    
        return KErrBadName;
    }

    __PRINTF(aParams.ipDevName);
    
    ASSERT(!HandleValid() && ipScratchBuf);

    //-- open the device
    DWORD dwAccess = GENERIC_READ;
    
    if(!aParams.iReadOnly)
        dwAccess |= GENERIC_WRITE;  
    
    iDevHandle = CreateFileA(aParams.ipDevName,
                             dwAccess, 
                             FILE_SHARE_READ,
                             (LPSECURITY_ATTRIBUTES)NULL,
                             OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL,
                             NULL);

    if(!HandleValid())
    {
        __LOG1(_L("#-- CWinVolumeDevice::Connect() Error creating device handle! WinErr:%d"), GetLastError());
        return KErrGeneral;
    }     
    
    //-- find out device geometry
    iMediaType = Unknown;
    iDrvGeometry.iBytesPerSector = KDefaultSectorSz;

    DWORD junk; 

    //-- 1. try to query disk geometry, but it can produce wrong results for partitioned media
    BOOL bResult = DeviceIoControl(Handle(),
                                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                   NULL, 0,
                                   ipScratchBuf, KScratchBufSz,
                                   &junk, (LPOVERLAPPED)NULL);

    if(bResult)
    {
        const DISK_GEOMETRY& dg = (const DISK_GEOMETRY&)*ipScratchBuf;
        
        iDrvGeometry.iBytesPerSector = dg.BytesPerSector;
        iMediaType = dg.MediaType;

        __PRINT3(_L("#-- dev geometry: Cyl:%d Heads:%d Sectors:%d"), dg.Cylinders.LowPart, dg.TracksPerCylinder, dg.SectorsPerTrack);    
        __PRINT2(_L("#-- dev geometry: MediaType:%d, bps:%d"), dg.MediaType, dg.BytesPerSector);    

    }
    else
    {
        iMediaType = Unknown;
        iDrvGeometry.iBytesPerSector = KDefaultSectorSz;

        __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_DRIVE_GEOMETRY WinError:%d !"), GetLastError());
    }

    //-- 1.1 check "bytes per sector" value and how it corresponds to the request from parameters
    if(aParams.iDrvGeometry.iBytesPerSector == 0)
    {//-- do nothing, this parameter is not set in config file, use media's
    } 
    else if(aParams.iDrvGeometry.iBytesPerSector != iDrvGeometry.iBytesPerSector)
    {//-- we can't set "SectorSize" value for the physical media
        __LOG1(_L("#-- CWinVolumeDevice::Connect() can not use 'Sec. Size' value from config:%d !"), aParams.iDrvGeometry.iBytesPerSector);
        Disconnect();
        return KErrArgument;
    }


    ASSERT(IsPowerOf2(BytesPerSector()) && BytesPerSector() >= KDefaultSectorSz && BytesPerSector() < 4096);

    //-- find out partition information in order to determine volume size. 
    bResult = DeviceIoControl(Handle(),
                              IOCTL_DISK_GET_PARTITION_INFO,
                              NULL, 0,
                              ipScratchBuf, KScratchBufSz,
                              &junk, (LPOVERLAPPED)NULL);

    if(!bResult)
    {//-- this is a fatal error
        __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_PARTITION_INFO WinError:%d !"), GetLastError());
        Disconnect();
        return KErrBadHandle;    
    }

    //-- get partition informaton
    const PARTITION_INFORMATION& pi = (const PARTITION_INFORMATION&)*ipScratchBuf;
    TInt64 volSz = MAKE_TINT64(pi.PartitionLength.HighPart, pi.PartitionLength.LowPart);
    iDrvGeometry.iSizeInSectors = (TUint32)(volSz / iDrvGeometry.iBytesPerSector);
            
    __LOG3(_L("#-- partition size, bytes:%LU (%uMB), sectors:%u"), volSz, (TUint32)(volSz>>20), iDrvGeometry.iSizeInSectors);
   
    //-- check if the media size is set in coonfig and if we can use this setting.
    if(aParams.iDrvGeometry.iSizeInSectors == 0)
    {//-- do nothing, the media size is not set in the ini file, use existing media parameters
    }
    else if(aParams.iDrvGeometry.iSizeInSectors > iDrvGeometry.iSizeInSectors)
    {//-- requested media size in ini file is bigger than physical media, error.
     //-- we can't increase physical media size
    __LOG2(_L("#-- CWinVolumeDevice::Connect() 'MediaSizeSectors' value from config:%d > than physical:%d !"), aParams.iDrvGeometry.iSizeInSectors, iDrvGeometry.iSizeInSectors);
    Disconnect();
    return KErrArgument;
    }
    else if(aParams.iDrvGeometry.iSizeInSectors < iDrvGeometry.iSizeInSectors)
    {//-- settings specify smaller media than physical one, adjust the size
    __PRINT1(_L("#-- reducing media size to %d sectors"), aParams.iDrvGeometry.iSizeInSectors);
    iDrvGeometry.iSizeInSectors = aParams.iDrvGeometry.iSizeInSectors;
    }


    ASSERT(iDrvGeometry.iSizeInSectors > KMinMediaSizeInSectors);
    return KErrNone;
}
INT_BOOL IsPowerOf8Const(const unsigned num) {
    return IsPowerOf2(num) and not(num & 0xB6DB6DB6);
}
Esempio n. 18
0
bool TestSettings()
{
	bool pass = true;

	cout << "\nTesting Settings...\n\n";

	if (*(word32 *)"\x01\x02\x03\x04" == 0x04030201L)
	{
#ifdef IS_LITTLE_ENDIAN
		cout << "passed:  ";
#else
		cout << "FAILED:  ";
		pass = false;
#endif
		cout << "Your machine is little endian.\n";
	}
	else if (*(word32 *)"\x01\x02\x03\x04" == 0x01020304L)
	{
#ifndef IS_LITTLE_ENDIAN
		cout << "passed:  ";
#else
		cout << "FAILED:  ";
		pass = false;
#endif
		cout << "Your machine is big endian.\n";
	}
	else
	{
		cout << "FAILED:  Your machine is neither big endian nor little endian.\n";
		pass = false;
	}

	if (sizeof(byte) == 1)
		cout << "passed:  ";
	else
	{
		cout << "FAILED:  ";
		pass = false;
	}
	cout << "sizeof(byte) == " << sizeof(byte) << endl;

	if (sizeof(word16) == 2)
		cout << "passed:  ";
	else
	{
		cout << "FAILED:  ";
		pass = false;
	}
	cout << "sizeof(word16) == " << sizeof(word16) << endl;

	if (sizeof(word32) == 4)
		cout << "passed:  ";
	else
	{
		cout << "FAILED:  ";
		pass = false;
	}
	cout << "sizeof(word32) == " << sizeof(word32) << endl;

#ifdef WORD64_AVAILABLE
	if (sizeof(word64) == 8)
		cout << "passed:  ";
	else
	{
		cout << "FAILED:  ";
		pass = false;
	}
	cout << "sizeof(word64) == " << sizeof(word64) << endl;
#elif defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE)
	if (sizeof(dword) >= 8)
	{
		cout << "FAILED:  sizeof(dword) >= 8, but WORD64_AVAILABLE not defined" << endl;
		pass = false;
	}
	else
		cout << "passed:  word64 not available" << endl;
#endif

#ifdef CRYPTOPP_WORD128_AVAILABLE
	if (sizeof(word128) == 16)
		cout << "passed:  ";
	else
	{
		cout << "FAILED:  ";
		pass = false;
	}
	cout << "sizeof(word128) == " << sizeof(word128) << endl;
#endif

	if (sizeof(word) == 2*sizeof(hword)
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
		&& sizeof(dword) == 2*sizeof(word)
#endif
		)
		cout << "passed:  ";
	else
	{
		cout << "FAILED:  ";
		pass = false;
	}
	cout << "sizeof(hword) == " << sizeof(hword) << ", sizeof(word) == " << sizeof(word);
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
	cout << ", sizeof(dword) == " << sizeof(dword);
#endif
	cout << endl;

	bool hasMMX = HasMMX();
	bool hasISSE = HasISSE();
	bool hasSSE2 = HasSSE2();
	bool hasSSSE3 = HasSSSE3();
	bool isP4 = IsP4();
	int cacheLineSize = GetCacheLineSize();

	if ((isP4 && (!hasMMX || !hasSSE2)) || (hasSSE2 && !hasMMX) || (cacheLineSize < 16 || cacheLineSize > 256 || !IsPowerOf2(cacheLineSize)))
	{
		cout << "FAILED:  ";
		pass = false;
	}
	else
		cout << "passed:  ";

	cout << "hasMMX == " << hasMMX << ", hasISSE == " << hasISSE << ", hasSSE2 == " << hasSSE2 << ", hasSSSE3 == " << hasSSSE3 << ", isP4 == " << isP4 << ", cacheLineSize == " << cacheLineSize;

	if (!pass)
	{
		cout << "Some critical setting in config.h is in error.  Please fix it and recompile." << endl;
		abort();
	}
	return pass;
}
Esempio n. 19
0
File: Crc.cpp Progetto: lcs2/carpg
inline T2 ModPowerOf2(const T1 &a, const T2 &b)
{
	assert(IsPowerOf2(b));
	return T2(a) & (b-1);
}
Esempio n. 20
0
File: Crc.cpp Progetto: lcs2/carpg
inline bool IsAlignedOn(const void *p, unsigned int alignment)
{
	return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0);
}
Esempio n. 21
0
void MetropolisRenderer::Render(const Scene *scene) {
    PBRT_MLT_STARTED_RENDERING();
    if (scene->lights.size() > 0) {
        int x0, x1, y0, y1;
        camera->film->GetPixelExtent(&x0, &x1, &y0, &y1);
        float t0 = camera->shutterOpen, t1 = camera->shutterClose;
        Distribution1D *lightDistribution = ComputeLightSamplingCDF(scene);

        if (directLighting != NULL) {
            PBRT_MLT_STARTED_DIRECTLIGHTING();
            // Compute direct lighting before Metropolis light transport
            if (nDirectPixelSamples > 0) {
                LDSampler sampler(x0, x1, y0, y1, nDirectPixelSamples, t0, t1);
                Sample *sample = new Sample(&sampler, directLighting, NULL, scene);
                vector<Task *> directTasks;
                int nDirectTasks = max(32 * NumSystemCores(),
                                 (camera->film->xResolution * camera->film->yResolution) / (16*16));
                nDirectTasks = RoundUpPow2(nDirectTasks);
                ProgressReporter directProgress(nDirectTasks, "Direct Lighting");
                for (int i = 0; i < nDirectTasks; ++i)
                    directTasks.push_back(new SamplerRendererTask(scene, this, camera, directProgress,
                                                                  &sampler, sample, false, i, nDirectTasks));
                std::reverse(directTasks.begin(), directTasks.end());
                EnqueueTasks(directTasks);
                WaitForAllTasks();
                for (uint32_t i = 0; i < directTasks.size(); ++i)
                    delete directTasks[i];
                delete sample;
                directProgress.Done();
            }
            camera->film->WriteImage();
            PBRT_MLT_FINISHED_DIRECTLIGHTING();
        }
        // Take initial set of samples to compute $b$
        PBRT_MLT_STARTED_BOOTSTRAPPING(nBootstrap);
        RNG rng(0);
        MemoryArena arena;
        vector<float> bootstrapI;
        vector<PathVertex> cameraPath(maxDepth, PathVertex());
        vector<PathVertex> lightPath(maxDepth, PathVertex());
        float sumI = 0.f;
        bootstrapI.reserve(nBootstrap);
        MLTSample sample(maxDepth);
        for (uint32_t i = 0; i < nBootstrap; ++i) {
            // Generate random sample and path radiance for MLT bootstrapping
            float x = Lerp(rng.RandomFloat(), x0, x1);
            float y = Lerp(rng.RandomFloat(), y0, y1);
            LargeStep(rng, &sample, maxDepth, x, y, t0, t1, bidirectional);
            Spectrum L = PathL(sample, scene, arena, camera, lightDistribution,
                               &cameraPath[0], &lightPath[0], rng);

            // Compute contribution for random sample for MLT bootstrapping
            float I = ::I(L);
            sumI += I;
            bootstrapI.push_back(I);
            arena.FreeAll();
        }
        float b = sumI / nBootstrap;
        PBRT_MLT_FINISHED_BOOTSTRAPPING(b);
        Info("MLT computed b = %f", b);

        // Select initial sample from bootstrap samples
        float contribOffset = rng.RandomFloat() * sumI;
        rng.Seed(0);
        sumI = 0.f;
        MLTSample initialSample(maxDepth);
        for (uint32_t i = 0; i < nBootstrap; ++i) {
            float x = Lerp(rng.RandomFloat(), x0, x1);
            float y = Lerp(rng.RandomFloat(), y0, y1);
            LargeStep(rng, &initialSample, maxDepth, x, y, t0, t1,
                      bidirectional);
            sumI += bootstrapI[i];
            if (sumI > contribOffset)
                break;
        }

        // Launch tasks to generate Metropolis samples
        uint32_t nTasks = largeStepsPerPixel;
        uint32_t largeStepRate = nPixelSamples / largeStepsPerPixel;
        Info("MLT running %d tasks, large step rate %d", nTasks, largeStepRate);
        ProgressReporter progress(nTasks * largeStepRate, "Metropolis");
        vector<Task *> tasks;
        Mutex *filmMutex = Mutex::Create();
        Assert(IsPowerOf2(nTasks));
        uint32_t scramble[2] = { rng.RandomUInt(), rng.RandomUInt() };
        uint32_t pfreq = (x1-x0) * (y1-y0);
        for (uint32_t i = 0; i < nTasks; ++i) {
            float d[2];
            Sample02(i, scramble, d);
            tasks.push_back(new MLTTask(progress, pfreq, i,
                d[0], d[1], x0, x1, y0, y1, t0, t1, b, initialSample,
                scene, camera, this, filmMutex, lightDistribution));
        }
        EnqueueTasks(tasks);
        WaitForAllTasks();
        for (uint32_t i = 0; i < tasks.size(); ++i)
            delete tasks[i];
        progress.Done();
        Mutex::Destroy(filmMutex);
        delete lightDistribution;
    }
    camera->film->WriteImage();
    PBRT_MLT_FINISHED_RENDERING();
}
/** Check if given number is a power of d where d is a power of 2
 *
 * @reference   https://www.geeksforgeeks.org/check-given-number-power-d-d-power-2/
 *
 * Given an integer n, find whether it is a power of d or not,
 * where d is itself a power of 2.
 */
INT_BOOL IsPowerOfPowerOf2(const unsigned n, const unsigned d) {
    return IsPowerOf2(n) and (CountTrailingZerosLinear(n) % static_cast<unsigned>(log2(d))) == 0;
}