82 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdint.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <math.h>
 | |
| #include <time.h>
 | |
| 
 | |
| /* This could be built with one opamp for the multiplier, a comparator with
 | |
|    rail-to-rail outputs, and switches and caps and resistors.*/
 | |
| static inline uint8_t updateA(long double *A, long double K, long double noise) {
 | |
|     if(*A > 1.0) {
 | |
|         *A = 1.0;
 | |
|     } else if (*A < 0.0) {
 | |
|         *A = 0.0;
 | |
|     }
 | |
|     *A += noise;
 | |
|     if(*A > 0.5) {
 | |
|         *A = K**A - (K-1);
 | |
|         return 1;
 | |
|     }
 | |
|     *A += noise;
 | |
|     *A = K**A;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static inline uint32_t computeRandBits(long double *A, uint32_t N, long double K, long double noiseAmplitude) {
 | |
|     uint32_t bits = 0;
 | |
|     for(uint32_t i = 0; i < N; i++) {
 | |
|         //printf("%f\n", (double)*A);
 | |
|         long double noise = noiseAmplitude*(((double)rand()/RAND_MAX) - 0.5);
 | |
|         uint8_t result = updateA(A, K, noise);
 | |
|         bits = (bits << 1) | result;
 | |
|     }
 | |
|     return bits;
 | |
| }
 | |
| 
 | |
| static uint32_t computeMax(uint32_t *values, uint32_t numRuns, uint32_t N, long double K,
 | |
|         long double noiseAmplitude, uint32_t *maxValue) {
 | |
|     long double A = 0.0;
 | |
| 
 | |
|     memset(values, 0, (1 << N)*sizeof(uint32_t));
 | |
|     computeRandBits(&A, 30, K, noiseAmplitude); // Randomize state
 | |
|     for(uint32_t i = 0; i < numRuns; i++) {
 | |
|         uint32_t value = computeRandBits(&A, N, K, noiseAmplitude); // Randomize state
 | |
|         //printf("%u\n", value);
 | |
|         values[value]++;
 | |
|     }
 | |
|     *maxValue = 0;
 | |
|     uint32_t maxOccurance = 0;
 | |
|     for(uint32_t i = 0; i < 1 << N; i++) {
 | |
|         uint32_t occurance = values[i];
 | |
|         if(occurance > maxOccurance) {
 | |
|             maxOccurance = occurance;
 | |
|             *maxValue = i;
 | |
|         }
 | |
|     }
 | |
|     printf("Max occurance at K=%.2f: %u.  Most common value was %x\n", (double)K, maxOccurance, *maxValue);
 | |
|     return maxOccurance;
 | |
| }
 | |
| 
 | |
| int main() {
 | |
|     uint32_t N = 18;
 | |
|     long double noiseAmplitude = 1.0/(1 << 20);
 | |
|     uint32_t numRuns = 1 << 26;
 | |
|     //long double K = sqrt(2.0);
 | |
|     long double K = 1.8;
 | |
|     uint32_t *values = calloc(1 << N, sizeof(uint32_t));
 | |
| 
 | |
|     srand(time(NULL));
 | |
|     uint32_t maxValue1, maxValue2;
 | |
|     computeMax(values, numRuns, N, 2.0, noiseAmplitude, &maxValue1);
 | |
|     computeMax(values, numRuns, N, 2.0, noiseAmplitude, &maxValue2);
 | |
|     uint32_t max1 = values[maxValue1];
 | |
|     printf("max1 = %u, total bits = %f\n", max1, log((double)numRuns/max1)/log(2.0));
 | |
|     computeMax(values, numRuns, N, K, noiseAmplitude, &maxValue1);
 | |
|     computeMax(values, numRuns, N, K, noiseAmplitude, &maxValue2);
 | |
|     uint32_t max2 = values[maxValue1];
 | |
|     printf("max2 = %u, total bits = %f\n", max2, log((double)numRuns/max2)/log(2.0));
 | |
|     printf("Computed bits/clock: %f\n", log(numRuns/max2)/log(numRuns/max1));
 | |
|     printf("Estimated bits/clock: %f\n", log(K)/log(2.0));
 | |
| }
 |