#include "stdafx.h" #include "GenePiece.h" #include "Simulation.h" #include "Population.h" #include "Person.h" #include #include struct GenePiece *GenePiece_malloc( struct Simulation *sim, struct Person *founder ) { return GenePiece_malloc( NULL, sim->crossoverSites, founder ); } struct GenePiece *GenePiece_malloc( struct GenePiece *nextPiece, int size, struct Person *foundingPerson ) { struct GenePiece *gp; // Allocate a new gene piece. gp = (struct GenePiece *) malloc( sizeof( struct GenePiece ) ); // Set the default initial values. gp->nextPiece = nextPiece; gp->size = size; gp->founder = foundingPerson; // Return a pointer to the allocated gene piece. return gp; } struct GenePiece *GenePiece_copy( struct GenePiece *original ) { struct GenePiece *gp; // Create a copy with the original gene's size and founder. gp = GenePiece_malloc( NULL, original->size, original->founder ); // If the piece we are copying had a following link, copy that too. if( original->nextPiece ) gp->nextPiece = GenePiece_copy( original->nextPiece ); // Return a pointer to the allocated gene piece. return gp; } void GenePiece_crossover( struct GenePiece *gp1, struct GenePiece *gp2, int site ) { int site1; int site2; struct GenePiece *newPiece1; struct GenePiece *newPiece2; site1 = site; site2 = site; // Find the gene pieces and locations within them where the crossover occurs. while( site1 >= gp1->size ) { site1 -= gp1->size; // If site1 == 0 (we hit an existing crossover point), we won't be allocating a new GenePiece. // Keep the previous pointer so we can change its nextPiece link. if( site1 ) gp1 = gp1->nextPiece; } while( site2 >= gp2->size ) { site2 -= gp2->size; // If site2 == 0 (we hit an existing crossover point), we won't be allocating a new GenePiece. // Keep the previous pointer so we can change its nextPiece link. if( site2 ) gp2 = gp2->nextPiece; } // If this is a new crossover breakpoint for chromosome half 1... if( site1 ) { // Cut up the chromosome. newPiece1 = GenePiece_malloc( gp1->nextPiece, gp1->size - site1, gp1->founder ); gp1->nextPiece = newPiece1; gp1->size = site1; } else newPiece1 = gp1->nextPiece; // If this is a new crossover breakpoint for chromosome half 2... if( site2 ) { // Cut up the chromosome. newPiece2 = GenePiece_malloc( gp2->nextPiece, gp2->size - site2, gp2->founder ); gp2->nextPiece = newPiece2; gp2->size = site2; } else newPiece2 = gp2->nextPiece; // Swap the links. gp1->nextPiece = newPiece2; gp2->nextPiece = newPiece1; } int GenePiece_elementCount( struct GenePiece *gp ) { int count = 0; while( gp ) { count ++; gp = gp->nextPiece; } return count; } float GenePiece_founderGenePercentage( struct GenePiece *gp, struct Person *founder ) { int totalFromFounder = 0, totalSize = 0; struct GenePiece *thisPiece; thisPiece = gp; while( thisPiece ) { totalSize += thisPiece->size; if( thisPiece->founder == founder ) totalFromFounder += thisPiece->size; thisPiece = thisPiece->nextPiece; } return (float)( totalFromFounder ) / (float)( totalSize ); } bool GenePiece_hasFounderGenes( struct GenePiece *gp, struct Person *founder ) { struct GenePiece *thisPiece; thisPiece = gp; while( thisPiece ) { if( thisPiece->founder == founder ) return true; thisPiece = thisPiece->nextPiece; } return false; } float GenePiece_maleGenePercentage( struct GenePiece *gp ) { int totalFromMales = 0, totalSize = 0; struct GenePiece *thisPiece; thisPiece = gp; while( thisPiece ) { totalSize += thisPiece->size; if( thisPiece->founder->genderIsMale ) totalFromMales += thisPiece->size; thisPiece = thisPiece->nextPiece; } return (float)( totalFromMales ) / (float)( totalSize ); } void GenePiece_free( struct GenePiece *gp ) { // Recursively free any following pieces. if( gp->nextPiece ) GenePiece_free( gp->nextPiece ); // Free the gene piece from memory. free( gp ); } void GenePiece_save( struct GenePiece *gp, FILE *out ) { int pieces; pieces = GenePiece_elementCount( gp ); fwrite( &pieces, sizeof( pieces ), 1, out ); while( gp ) { fwrite( &( gp->founder->genderIsMale ), sizeof( gp->founder->genderIsMale ), 1, out ); fwrite( &( gp->founder->index ), sizeof( gp->founder->index ), 1, out ); fwrite( &( gp->size ), sizeof( gp->size ), 1, out ); gp = gp->nextPiece; } } struct GenePiece *GenePiece_load( FILE *in, struct Simulation *sim ) { struct GenePiece *gp, *thisPiece; int pieces; bool genderIsMale; int index; fread( &pieces, sizeof( pieces ), 1, in ); if( ! pieces ) return NULL; gp = (struct GenePiece *) malloc( sizeof( struct GenePiece ) ); fread( &( genderIsMale ), sizeof( genderIsMale ), 1, in ); fread( &( index ), sizeof( index ), 1, in ); if( genderIsMale ) gp->founder = sim->generations[ 0 ]->males[ index ]; else gp->founder = sim->generations[ 0 ]->females[ index ]; fread( &( gp->size ), sizeof( gp->size ), 1, in ); thisPiece = gp; pieces --; while( pieces ) { thisPiece->nextPiece = (struct GenePiece *) malloc( sizeof( struct GenePiece ) ); thisPiece = thisPiece->nextPiece; pieces --; fread( &( genderIsMale ), sizeof( genderIsMale ), 1, in ); fread( &( index ), sizeof( index ), 1, in ); if( genderIsMale ) thisPiece->founder = sim->generations[ 0 ]->males[ index ]; else thisPiece->founder = sim->generations[ 0 ]->females[ index ]; fread( &( thisPiece->size ), sizeof( thisPiece->size ), 1, in ); } thisPiece->nextPiece = NULL; return gp; }