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 }