github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/test/cmplxdivide.c (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This C program generates the file cmplxdivide1.go. It uses the 6 // output of the operations by C99 as the reference to check 7 // the implementation of complex numbers in Go. 8 // The generated file, cmplxdivide1.go, is compiled along 9 // with the driver cmplxdivide.go (the names are confusing 10 // and unimaginative) to run the actual test. This is done by 11 // the usual test runner. 12 // 13 // The file cmplxdivide1.go is checked in to the repository, but 14 // if it needs to be regenerated, compile and run this C program 15 // like this: 16 // gcc '-std=c99' cmplxdivide.c && a.out >cmplxdivide1.go 17 18 #include <complex.h> 19 #include <math.h> 20 #include <stdio.h> 21 #include <string.h> 22 23 #define nelem(x) (sizeof(x)/sizeof((x)[0])) 24 25 double f[] = { 26 0, 27 1, 28 -1, 29 2, 30 NAN, 31 INFINITY, 32 -INFINITY, 33 }; 34 35 char* 36 fmt(double g) 37 { 38 static char buf[10][30]; 39 static int n; 40 char *p; 41 42 p = buf[n++]; 43 if(n == 10) 44 n = 0; 45 sprintf(p, "%g", g); 46 if(strcmp(p, "-0") == 0) 47 strcpy(p, "negzero"); 48 return p; 49 } 50 51 int 52 iscnan(double complex d) 53 { 54 return !isinf(creal(d)) && !isinf(cimag(d)) && (isnan(creal(d)) || isnan(cimag(d))); 55 } 56 57 double complex zero; // attempt to hide zero division from gcc 58 59 int 60 main(void) 61 { 62 int i, j, k, l; 63 double complex n, d, q; 64 65 printf("// skip\n"); 66 printf("// # generated by cmplxdivide.c\n"); 67 printf("\n"); 68 printf("package main\n"); 69 printf("var tests = []Test{\n"); 70 for(i=0; i<nelem(f); i++) 71 for(j=0; j<nelem(f); j++) 72 for(k=0; k<nelem(f); k++) 73 for(l=0; l<nelem(f); l++) { 74 n = f[i] + f[j]*I; 75 d = f[k] + f[l]*I; 76 q = n/d; 77 78 // BUG FIX. 79 // Gcc gets the wrong answer for NaN/0 unless both sides are NaN. 80 // That is, it treats (NaN+NaN*I)/0 = NaN+NaN*I (a complex NaN) 81 // but it then computes (1+NaN*I)/0 = Inf+NaN*I (a complex infinity). 82 // Since both numerators are complex NaNs, it seems that the 83 // results should agree in kind. Override the gcc computation in this case. 84 if(iscnan(n) && d == 0) 85 q = (NAN+NAN*I) / zero; 86 87 printf("\tTest{complex(%s, %s), complex(%s, %s), complex(%s, %s)},\n", 88 fmt(creal(n)), fmt(cimag(n)), 89 fmt(creal(d)), fmt(cimag(d)), 90 fmt(creal(q)), fmt(cimag(q))); 91 } 92 printf("}\n"); 93 return 0; 94 }