/ src / tests / mathtest.c
mathtest.c
  1  /********************************************************************
  2  * Description: mathtest.c - A small file to test for unresolved
  3  *                        symbols in loadable kernel modules.
  4  *
  5  * Author: Paul_C - Derived from a file by Fred Proctor.
  6  * Created at: Mon Feb 16 20:39:42 GMT 2004
  7  * Computer: Morphix 
  8  * System: Linux
  9  *    
 10  * Copyright (c) 2004 All rights reserved.
 11  *
 12  * Last change: 
 13  ********************************************************************/
 14  /*
 15  * This program is free software; you can redistribute it and/or modify
 16  * it under the terms of the GNU General Public License as published by
 17  * the Free Software Foundation; either version 2 of the License, or
 18  * (at your option) any later version.
 19  *
 20  * This program is distributed in the hope that it will be useful,
 21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 23  * GNU General Public License for more details.
 24  *
 25  * You should have received a copy of the GNU General Public License
 26  * along with this program; if not, write to the Free Software
 27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 28  */
 29  
 30  #define MODULE
 31  #include <linux/kernel.h>
 32  #include <linux/module.h>
 33  #include <linux/version.h>
 34  #include <math.h>		/* sin(), cos(), isnan() etc. */
 35  #include <float.h>		/* DBL_MAX */
 36  #include <errno.h>		/* errno, EDOM */
 37  
 38  /*
 39    math functions are:
 40  
 41    extern double sin(double);            used in posemath, siggen, & noncartesian kins
 42    extern double cos(double);            used in posemath, siggen, & noncartesian kins
 43    extern double tan(double);            not used in RT
 44    extern double asin(double);           not used in RT
 45    extern double acos(double);           used in posemath & noncartesian kins
 46    extern double atan2(double, double);  used in posemath & noncartesian kins
 47    extern double sinh(double);           not used in RT
 48    extern double cosh(double);           not used in RT
 49    extern double tanh(double);           not used in RT
 50    extern double exp(double);            not used in RT
 51    extern double log(double);            not used in RT
 52    extern double log10(double);          not used in RT
 53    extern double pow(double, double);    not used in RT
 54    extern double sqrt(double);           used in tc, segmot, & noncartesean kins.
 55    extern double ceil(double);           used in segmot & emcpid
 56    extern double floor(double);          used by siggen & segmot
 57    extern double fabs(double);           used a lot in RT
 58    extern double ldexp(double, int);     not used in RT
 59  
 60    extern double sincos(double, double *, double *); Is called at four places in
 61                                                      posemath - None of the resulting
 62                                                      functions are used in EMC.
 63    Extras:
 64  
 65    extern int isnan(double);             Not used directly in RT - But is called
 66                                          by several (all ?) of the floating point
 67  					math functions.
 68  */
 69  
 70  /* Declare as volatile and gcc *shouldn't* optimize too much... */
 71  volatile double a = 0;
 72  volatile double b = 0;
 73  volatile double c = 0;
 74  volatile double x;
 75  double d;
 76  int n;
 77  
 78  /*
 79    isnan() - C99 extensions to the math library functions
 80  
 81    IEEE double-precision floating point:
 82  
 83    N = (-1)^S * 2^(E-1023) * 1.F
 84  
 85    where S, E and F are composed of bits as labeled in these 8 bytes:
 86  
 87    [7]      [6]      [5]          [0]
 88    SEEEEEEE EEEEFFFF FFFFFFFF ... FFFFFFFF
 89  
 90    If E = 2047 and F is nonzero, N = Not a Number (NaN)
 91    If E = 2047 and F = 0 and S = 1, N = -Inf
 92    If E = 2047 and F = 0 and S = 0, N = Inf
 93    If 0 < E < 2047, N = (-1)^S * 2^(E-1023) * 1.F
 94    If E = 0 and F is nonzero, N = (-1)^S * 2^(-1022) * 0.F ("unnormalized")
 95    If E = 0 and F = 0 and S = 1, N = -0
 96    If E = 0 and F = 0 and S = 0, N = 0
 97  
 98    Example: for N = -1, S = 1, E = 1023, F = 0, and
 99    byte[0] = 10111111 = BF
100    byte[1] = 11110000 = F0
101    byte[2-7] = 0
102  */
103  
104  int isnan(double d)
105  {
106    int e;
107    unsigned char * c = (unsigned char *) &d;
108  
109    e = (int) (c[7] & 0x7F);
110    e <<= 4;
111    e += (int) ((c[6] & 0xF0) >> 4);
112  
113    return (e == 2047) && (c[0] || c[1] || c[2] || c[3] || 
114  			 c[4] || c[5] || (c[6] & 0x0F));
115  }
116  
117  int math_test(void)
118  {
119    double v, u;
120    a = 1.00039276;
121    b = 1.9999 * a;
122    c = a / 2;
123  
124    /* force a domain error, EDOM, and check that we got it */
125    x = acos(b);
126    if (isnan(x)) x = 0.0;
127  
128    /* force a range error, ERANGE, and check that we got it */
129    x = pow(DBL_MAX, b);
130    if (isnan(x)) x = 0.0;
131  
132    /* do some legit math */
133    x = sin(a) + cos(a) + tan(a) + 
134        asin(c) + acos(c) + atan2(a, b) +
135        sinh(a) + cosh(a) + tanh(a) + 
136        exp(a) + log(a) + log10(a) + 
137        pow(a, b) + sqrt(a) + ceil(a) + 
138        floor(a) + fabs(a) + ldexp(a, b);
139  
140    /* Test the sincos func */
141    sincos(x, &v, &u);
142  
143    return 0;
144  }