2 * Included file to common source float/double checking
3 * The following macros should be defined:
4 * TYPE -- floating point type
5 * NAME -- convert a name to include the type
6 * UNS_TYPE -- type to hold TYPE as an unsigned number
7 * EXP_SIZE -- size in bits of the exponent
8 * MAN_SIZE -- size in bits of the mantissa
9 * UNS_ABS -- absolute value for UNS_TYPE
10 * FABS -- absolute value function for TYPE
11 * FMAX -- maximum function for TYPE
12 * FMIN -- minimum function for TYPE
13 * SQRT -- square root function for TYPE
14 * RMIN -- minimum random number to generate
15 * RMAX -- maximum random number to generate
16 * ASMDIV -- assembler instruction to do divide
17 * ASMSQRT -- assembler instruction to do square root
18 * BDIV -- # of bits of inaccuracy to allow for division
19 * BRSQRT -- # of bits of inaccuracy to allow for 1/sqrt
20 * INIT_DIV -- Initial values to test 1/x against
21 * INIT_RSQRT -- Initial values to test 1/sqrt(x) against
31 * Input/output arrays.
34 static NAME (union) NAME (div_input
) [] __attribute__((__aligned__(32))) = INIT_DIV
;
35 static NAME (union) NAME (rsqrt_input
)[] __attribute__((__aligned__(32))) = INIT_RSQRT
;
37 #define DIV_SIZE (sizeof (NAME (div_input)) / sizeof (TYPE))
38 #define RSQRT_SIZE (sizeof (NAME (rsqrt_input)) / sizeof (TYPE))
40 static TYPE
NAME (div_expected
)[DIV_SIZE
] __attribute__((__aligned__(32)));
41 static TYPE
NAME (div_output
) [DIV_SIZE
] __attribute__((__aligned__(32)));
43 static TYPE
NAME (rsqrt_expected
)[RSQRT_SIZE
] __attribute__((__aligned__(32)));
44 static TYPE
NAME (rsqrt_output
) [RSQRT_SIZE
] __attribute__((__aligned__(32)));
48 * Crack a floating point number into sign bit, exponent, and mantissa.
52 NAME (crack
) (TYPE number
, unsigned int *p_sign
, unsigned *p_exponent
, UNS_TYPE
*p_mantissa
)
60 *p_sign
= (unsigned int)((bits
>> (EXP_SIZE
+ MAN_SIZE
)) & 0x1);
61 *p_exponent
= (unsigned int)((bits
>> MAN_SIZE
) & ((((UNS_TYPE
)1) << EXP_SIZE
) - 1));
62 *p_mantissa
= bits
& ((((UNS_TYPE
)1) << MAN_SIZE
) - 1);
68 * Prevent optimizer from eliminating + 0.0 to remove -0.0.
71 volatile TYPE
NAME (math_diff_0
) = ((TYPE
) 0.0);
74 * Return negative if two numbers are significanly different or return the
75 * number of bits that are different in the mantissa.
79 NAME (math_diff
) (TYPE a
, TYPE b
, int bits
)
81 TYPE zero
= NAME (math_diff_0
);
82 unsigned int sign_a
, sign_b
;
83 unsigned int exponent_a
, exponent_b
;
84 UNS_TYPE mantissa_a
, mantissa_b
, diff
;
87 /* eliminate signed zero. */
91 /* special case Nan. */
92 if (__builtin_isnan (a
))
93 return (__builtin_isnan (b
) ? 0 : -1);
98 /* special case infinity. */
99 if (__builtin_isinf (a
))
100 return (__builtin_isinf (b
) ? 0 : -1);
102 /* punt on denormal numbers. */
103 if (!__builtin_isnormal (a
) || !__builtin_isnormal (b
))
106 NAME (crack
) (a
, &sign_a
, &exponent_a
, &mantissa_a
);
107 NAME (crack
) (b
, &sign_b
, &exponent_b
, &mantissa_b
);
109 /* If the sign is different, there is no hope. */
110 if (sign_a
!= sign_b
)
113 /* If the exponent is off by 1, see if the values straddle the power of two,
114 and adjust things to do the mantassa check if we can. */
115 if ((exponent_a
== (exponent_b
+1)) || (exponent_a
== (exponent_b
-1)))
117 TYPE big
= FMAX (a
, b
);
118 TYPE small
= FMIN (a
, b
);
119 TYPE diff
= FABS (a
- b
);
120 unsigned int sign_big
, sign_small
, sign_test
;
121 unsigned int exponent_big
, exponent_small
, exponent_test
;
122 UNS_TYPE mantissa_big
, mantissa_small
, mantissa_test
;
124 NAME (crack
) (big
, &sign_big
, &exponent_big
, &mantissa_big
);
125 NAME (crack
) (small
, &sign_small
, &exponent_small
, &mantissa_small
);
127 NAME (crack
) (small
- diff
, &sign_test
, &exponent_test
, &mantissa_test
);
128 if ((sign_test
== sign_small
) && (exponent_test
== exponent_small
))
130 mantissa_a
= mantissa_small
;
131 mantissa_b
= mantissa_test
;
136 NAME (crack
) (big
+ diff
, &sign_test
, &exponent_test
, &mantissa_test
);
137 if ((sign_test
== sign_big
) && (exponent_test
== exponent_big
))
139 mantissa_a
= mantissa_big
;
140 mantissa_b
= mantissa_test
;
148 else if (exponent_a
!= exponent_b
)
151 diff
= UNS_ABS (mantissa_a
- mantissa_b
);
152 for (i
= MAN_SIZE
; i
> 0; i
--)
154 if ((diff
& ((UNS_TYPE
)1) << (i
-1)) != 0)
163 * Turn off inlining to make code inspection easier.
166 static void NAME (asm_div
) (void) __attribute__((__noinline__
));
167 static void NAME (vector_div
) (void) __attribute__((__noinline__
));
168 static void NAME (scalar_div
) (void) __attribute__((__noinline__
));
169 static void NAME (asm_rsqrt
) (void) __attribute__((__noinline__
));
170 static void NAME (vector_rsqrt
) (void) __attribute__((__noinline__
));
171 static void NAME (scalar_rsqrt
) (void) __attribute__((__noinline__
));
172 static void NAME (check_div
) (const char *) __attribute__((__noinline__
));
173 static void NAME (check_rsqrt
) (const char *) __attribute__((__noinline__
));
174 static void NAME (run
) (void) __attribute__((__noinline__
));
178 * Division function that might be vectorized.
182 NAME (vector_div
) (void)
186 for (i
= 0; i
< DIV_SIZE
; i
++)
187 NAME (div_output
)[i
] = ((TYPE
) 1.0) / NAME (div_input
)[i
].x
;
191 * Division function that is not vectorized.
195 NAME (scalar_div
) (void)
199 for (i
= 0; i
< DIV_SIZE
; i
++)
201 TYPE x
= ((TYPE
) 1.0) / NAME (div_input
)[i
].x
;
203 __asm__ ("" : "=d" (y
) : "0" (x
));
204 NAME (div_output
)[i
] = y
;
209 * Generate the division instruction via asm.
213 NAME (asm_div
) (void)
217 for (i
= 0; i
< DIV_SIZE
; i
++)
220 __asm__ (ASMDIV
" %0,%1,%2"
222 : "d" ((TYPE
) 1.0), "d" (NAME (div_input
)[i
].x
));
223 NAME (div_expected
)[i
] = x
;
228 * Reciprocal square root function that might be vectorized.
232 NAME (vector_rsqrt
) (void)
236 for (i
= 0; i
< RSQRT_SIZE
; i
++)
237 NAME (rsqrt_output
)[i
] = ((TYPE
) 1.0) / SQRT (NAME (rsqrt_input
)[i
].x
);
241 * Reciprocal square root function that is not vectorized.
245 NAME (scalar_rsqrt
) (void)
249 for (i
= 0; i
< RSQRT_SIZE
; i
++)
251 TYPE x
= ((TYPE
) 1.0) / SQRT (NAME (rsqrt_input
)[i
].x
);
253 __asm__ ("" : "=d" (y
) : "0" (x
));
254 NAME (rsqrt_output
)[i
] = y
;
259 * Generate the 1/sqrt instructions via asm.
263 NAME (asm_rsqrt
) (void)
267 for (i
= 0; i
< RSQRT_SIZE
; i
++)
271 __asm__ (ASMSQRT
" %0,%1" : "=d" (x
) : "d" (NAME (rsqrt_input
)[i
].x
));
272 __asm__ (ASMDIV
" %0,%1,%2" : "=d" (y
) : "d" ((TYPE
) 1.0), "d" (x
));
273 NAME (rsqrt_expected
)[i
] = y
;
279 * Functions to abort or report errors.
282 static int NAME (error_count
) = 0;
285 static int NAME (max_bits_div
) = 0;
286 static int NAME (max_bits_rsqrt
) = 0;
291 * Compare the expected value with the value we got.
295 NAME (check_div
) (const char *test
)
300 for (i
= 0; i
< DIV_SIZE
; i
++)
302 TYPE exp
= NAME (div_expected
)[i
];
303 TYPE out
= NAME (div_output
)[i
];
304 b
= NAME (math_diff
) (exp
, out
, BDIV
);
309 NAME (union) u_in
= NAME (div_input
)[i
];
312 char explanation
[64];
320 sprintf (explanation
, "%d bit error%s", b
, (b
> BDIV
) ? ", failed" : "");
325 printf ("%s %s %s for 1.0 / %g [0x%llx], expected %g [0x%llx], got %g [0x%llx]\n",
326 TNAME (TYPE
), test
, p_exp
,
327 (double) u_in
.x
, (unsigned long long) u_in
.i
,
328 (double) exp
, (unsigned long long) u_exp
.i
,
329 (double) out
, (unsigned long long) u_out
.i
);
333 if (b
< 0 || b
> BDIV
)
334 NAME (error_count
)++;
337 if (b
> NAME (max_bits_div
))
338 NAME (max_bits_div
) = b
;
344 NAME (check_rsqrt
) (const char *test
)
349 for (i
= 0; i
< RSQRT_SIZE
; i
++)
351 TYPE exp
= NAME (rsqrt_expected
)[i
];
352 TYPE out
= NAME (rsqrt_output
)[i
];
353 b
= NAME (math_diff
) (exp
, out
, BRSQRT
);
358 NAME (union) u_in
= NAME (rsqrt_input
)[i
];
361 char explanation
[64];
369 sprintf (explanation
, "%d bit error%s", b
, (b
> BDIV
) ? ", failed" : "");
374 printf ("%s %s %s for 1 / sqrt (%g) [0x%llx], expected %g [0x%llx], got %g [0x%llx]\n",
375 TNAME (TYPE
), test
, p_exp
,
376 (double) u_in
.x
, (unsigned long long) u_in
.i
,
377 (double) exp
, (unsigned long long) u_exp
.i
,
378 (double) out
, (unsigned long long) u_out
.i
);
382 if (b
< 0 || b
> BRSQRT
)
383 NAME (error_count
)++;
386 if (b
> NAME (max_bits_rsqrt
))
387 NAME (max_bits_rsqrt
) = b
;
401 printf ("start run_%s, divide size = %ld, rsqrt size = %ld, %d bit%s for a/b, %d bit%s for 1/sqrt(a)\n",
405 BDIV
, (BDIV
== 1) ? "" : "s",
406 BRSQRT
, (BRSQRT
== 1) ? "" : "s");
411 NAME (scalar_div
) ();
412 NAME (check_div
) ("scalar");
414 NAME (vector_div
) ();
415 NAME (check_div
) ("vector");
419 NAME (scalar_rsqrt
) ();
420 NAME (check_rsqrt
) ("scalar");
422 NAME (vector_rsqrt
) ();
423 NAME (check_rsqrt
) ("vector");
426 printf ("end run_%s, errors = %d, max div bits = %d, max rsqrt bits = %d\n",
430 NAME (max_bits_rsqrt
));