Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 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 | |
Rob Pike | 3b63b69 | 2015-01-15 10:43:04 +1100 | [diff] [blame] | 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 |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 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; |
Russ Cox | 47c85ec | 2010-06-30 23:34:27 -0700 | [diff] [blame] | 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 |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 58 | |
| 59 | int |
| 60 | main(void) |
| 61 | { |
| 62 | int i, j, k, l; |
| 63 | double complex n, d, q; |
| 64 | |
Shenghou Ma | e266283 | 2012-03-22 02:14:44 +0800 | [diff] [blame] | 65 | printf("// skip\n"); |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 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; |
Russ Cox | 47c85ec | 2010-06-30 23:34:27 -0700 | [diff] [blame] | 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 | |
Russ Cox | f2b5a07 | 2011-01-19 23:09:00 -0500 | [diff] [blame] | 87 | printf("\tTest{complex(%s, %s), complex(%s, %s), complex(%s, %s)},\n", |
Russ Cox | 47c85ec | 2010-06-30 23:34:27 -0700 | [diff] [blame] | 88 | fmt(creal(n)), fmt(cimag(n)), |
| 89 | fmt(creal(d)), fmt(cimag(d)), |
| 90 | fmt(creal(q)), fmt(cimag(q))); |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 91 | } |
| 92 | printf("}\n"); |
| 93 | return 0; |
| 94 | } |