xref: /openbsd-src/lib/libm/src/math_private.h (revision 2f2c00629eff6a304ebffb255fc56f4fa7a1833b)
1*2f2c0062Sguenther /*	$OpenBSD: math_private.h,v 1.18 2016/09/12 19:47:02 guenther Exp $	*/
2df930be7Sderaadt /*
3df930be7Sderaadt  * ====================================================
4df930be7Sderaadt  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5df930be7Sderaadt  *
6df930be7Sderaadt  * Developed at SunPro, a Sun Microsystems, Inc. business.
7df930be7Sderaadt  * Permission to use, copy, modify, and distribute this
8df930be7Sderaadt  * software is freely granted, provided that this notice
9df930be7Sderaadt  * is preserved.
10df930be7Sderaadt  * ====================================================
11df930be7Sderaadt  */
12df930be7Sderaadt 
13df930be7Sderaadt /*
14df930be7Sderaadt  * from: @(#)fdlibm.h 5.1 93/09/24
15df930be7Sderaadt  */
16df930be7Sderaadt 
17df930be7Sderaadt #ifndef _MATH_PRIVATE_H_
18df930be7Sderaadt #define _MATH_PRIVATE_H_
19df930be7Sderaadt 
20df930be7Sderaadt #include <sys/types.h>
21df930be7Sderaadt 
22df930be7Sderaadt /* The original fdlibm code used statements like:
23df930be7Sderaadt 	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
24df930be7Sderaadt 	ix0 = *(n0+(int*)&x);			* high word of x *
25df930be7Sderaadt 	ix1 = *((1-n0)+(int*)&x);		* low word of x *
26df930be7Sderaadt    to dig two 32 bit words out of the 64 bit IEEE floating point
27df930be7Sderaadt    value.  That is non-ANSI, and, moreover, the gcc instruction
28df930be7Sderaadt    scheduler gets it wrong.  We instead use the following macros.
29df930be7Sderaadt    Unlike the original code, we determine the endianness at compile
30df930be7Sderaadt    time, not at run time; I don't see much benefit to selecting
31df930be7Sderaadt    endianness at run time.  */
32df930be7Sderaadt 
33a26ab1d9Smartynas /* A union which permits us to convert between a long double and
34a26ab1d9Smartynas    four 32 bit ints.  */
35a26ab1d9Smartynas 
36a26ab1d9Smartynas #if BYTE_ORDER == BIG_ENDIAN
37a26ab1d9Smartynas 
38a26ab1d9Smartynas typedef union
39a26ab1d9Smartynas {
40a26ab1d9Smartynas   long double value;
41a26ab1d9Smartynas   struct {
42a26ab1d9Smartynas     u_int32_t mswhi;
43a26ab1d9Smartynas     u_int32_t mswlo;
44a26ab1d9Smartynas     u_int32_t lswhi;
45a26ab1d9Smartynas     u_int32_t lswlo;
46a26ab1d9Smartynas   } parts32;
47a26ab1d9Smartynas   struct {
48a26ab1d9Smartynas     u_int64_t msw;
49a26ab1d9Smartynas     u_int64_t lsw;
50a26ab1d9Smartynas   } parts64;
51a26ab1d9Smartynas } ieee_quad_shape_type;
52a26ab1d9Smartynas 
53a26ab1d9Smartynas #endif
54a26ab1d9Smartynas 
55a26ab1d9Smartynas #if BYTE_ORDER == LITTLE_ENDIAN
56a26ab1d9Smartynas 
57a26ab1d9Smartynas typedef union
58a26ab1d9Smartynas {
59a26ab1d9Smartynas   long double value;
60a26ab1d9Smartynas   struct {
61a26ab1d9Smartynas     u_int32_t lswlo;
62a26ab1d9Smartynas     u_int32_t lswhi;
63a26ab1d9Smartynas     u_int32_t mswlo;
64a26ab1d9Smartynas     u_int32_t mswhi;
65a26ab1d9Smartynas   } parts32;
66a26ab1d9Smartynas   struct {
67a26ab1d9Smartynas     u_int64_t lsw;
68a26ab1d9Smartynas     u_int64_t msw;
69a26ab1d9Smartynas   } parts64;
70a26ab1d9Smartynas } ieee_quad_shape_type;
71a26ab1d9Smartynas 
72a26ab1d9Smartynas #endif
73a26ab1d9Smartynas 
74a26ab1d9Smartynas /* Get two 64 bit ints from a long double.  */
75a26ab1d9Smartynas 
76a26ab1d9Smartynas #define GET_LDOUBLE_WORDS64(ix0,ix1,d)				\
77a26ab1d9Smartynas do {								\
78a26ab1d9Smartynas   ieee_quad_shape_type qw_u;					\
79a26ab1d9Smartynas   qw_u.value = (d);						\
80a26ab1d9Smartynas   (ix0) = qw_u.parts64.msw;					\
81a26ab1d9Smartynas   (ix1) = qw_u.parts64.lsw;					\
82a26ab1d9Smartynas } while (0)
83a26ab1d9Smartynas 
84a26ab1d9Smartynas /* Set a long double from two 64 bit ints.  */
85a26ab1d9Smartynas 
86a26ab1d9Smartynas #define SET_LDOUBLE_WORDS64(d,ix0,ix1)				\
87a26ab1d9Smartynas do {								\
88a26ab1d9Smartynas   ieee_quad_shape_type qw_u;					\
89a26ab1d9Smartynas   qw_u.parts64.msw = (ix0);					\
90a26ab1d9Smartynas   qw_u.parts64.lsw = (ix1);					\
91a26ab1d9Smartynas   (d) = qw_u.value;						\
92a26ab1d9Smartynas } while (0)
93a26ab1d9Smartynas 
94a26ab1d9Smartynas /* Get the more significant 64 bits of a long double mantissa.  */
95a26ab1d9Smartynas 
96a26ab1d9Smartynas #define GET_LDOUBLE_MSW64(v,d)					\
97a26ab1d9Smartynas do {								\
98a26ab1d9Smartynas   ieee_quad_shape_type sh_u;					\
99a26ab1d9Smartynas   sh_u.value = (d);						\
100a26ab1d9Smartynas   (v) = sh_u.parts64.msw;					\
101a26ab1d9Smartynas } while (0)
102a26ab1d9Smartynas 
103a26ab1d9Smartynas /* Set the more significant 64 bits of a long double mantissa from an int.  */
104a26ab1d9Smartynas 
105a26ab1d9Smartynas #define SET_LDOUBLE_MSW64(d,v)					\
106a26ab1d9Smartynas do {								\
107a26ab1d9Smartynas   ieee_quad_shape_type sh_u;					\
108a26ab1d9Smartynas   sh_u.value = (d);						\
109a26ab1d9Smartynas   sh_u.parts64.msw = (v);					\
110a26ab1d9Smartynas   (d) = sh_u.value;						\
111a26ab1d9Smartynas } while (0)
112a26ab1d9Smartynas 
113a26ab1d9Smartynas /* Get the least significant 64 bits of a long double mantissa.  */
114a26ab1d9Smartynas 
115a26ab1d9Smartynas #define GET_LDOUBLE_LSW64(v,d)					\
116a26ab1d9Smartynas do {								\
117a26ab1d9Smartynas   ieee_quad_shape_type sh_u;					\
118a26ab1d9Smartynas   sh_u.value = (d);						\
119a26ab1d9Smartynas   (v) = sh_u.parts64.lsw;					\
120a26ab1d9Smartynas } while (0)
121a26ab1d9Smartynas 
122a26ab1d9Smartynas /* A union which permits us to convert between a long double and
123a26ab1d9Smartynas    three 32 bit ints.  */
124a26ab1d9Smartynas 
125a26ab1d9Smartynas #if BYTE_ORDER == BIG_ENDIAN
126a26ab1d9Smartynas 
127a26ab1d9Smartynas typedef union
128a26ab1d9Smartynas {
129a26ab1d9Smartynas   long double value;
130a26ab1d9Smartynas   struct {
131a26ab1d9Smartynas #ifdef __LP64__
132a26ab1d9Smartynas     int padh:32;
133a26ab1d9Smartynas #endif
134a26ab1d9Smartynas     int exp:16;
135a26ab1d9Smartynas     int padl:16;
136a26ab1d9Smartynas     u_int32_t msw;
137a26ab1d9Smartynas     u_int32_t lsw;
138a26ab1d9Smartynas   } parts;
139a26ab1d9Smartynas } ieee_extended_shape_type;
140a26ab1d9Smartynas 
141a26ab1d9Smartynas #endif
142a26ab1d9Smartynas 
143a26ab1d9Smartynas #if BYTE_ORDER == LITTLE_ENDIAN
144a26ab1d9Smartynas 
145a26ab1d9Smartynas typedef union
146a26ab1d9Smartynas {
147a26ab1d9Smartynas   long double value;
148a26ab1d9Smartynas   struct {
149a26ab1d9Smartynas     u_int32_t lsw;
150a26ab1d9Smartynas     u_int32_t msw;
151a26ab1d9Smartynas     int exp:16;
152a26ab1d9Smartynas     int padl:16;
153a26ab1d9Smartynas #ifdef __LP64__
154a26ab1d9Smartynas     int padh:32;
155a26ab1d9Smartynas #endif
156a26ab1d9Smartynas   } parts;
157a26ab1d9Smartynas } ieee_extended_shape_type;
158a26ab1d9Smartynas 
159a26ab1d9Smartynas #endif
160a26ab1d9Smartynas 
161a26ab1d9Smartynas /* Get three 32 bit ints from a double.  */
162a26ab1d9Smartynas 
16349393c00Smartynas #define GET_LDOUBLE_WORDS(se,ix0,ix1,d)				\
164a26ab1d9Smartynas do {								\
165a26ab1d9Smartynas   ieee_extended_shape_type ew_u;				\
166a26ab1d9Smartynas   ew_u.value = (d);						\
16749393c00Smartynas   (se) = ew_u.parts.exp;					\
168a26ab1d9Smartynas   (ix0) = ew_u.parts.msw;					\
169a26ab1d9Smartynas   (ix1) = ew_u.parts.lsw;					\
170a26ab1d9Smartynas } while (0)
171a26ab1d9Smartynas 
172a26ab1d9Smartynas /* Set a double from two 32 bit ints.  */
173a26ab1d9Smartynas 
17449393c00Smartynas #define SET_LDOUBLE_WORDS(d,se,ix0,ix1)				\
175a26ab1d9Smartynas do {								\
176a26ab1d9Smartynas   ieee_extended_shape_type iw_u;				\
17749393c00Smartynas   iw_u.parts.exp = (se);					\
178a26ab1d9Smartynas   iw_u.parts.msw = (ix0);					\
179a26ab1d9Smartynas   iw_u.parts.lsw = (ix1);					\
180a26ab1d9Smartynas   (d) = iw_u.value;						\
181a26ab1d9Smartynas } while (0)
182a26ab1d9Smartynas 
183a26ab1d9Smartynas /* Get the more significant 32 bits of a long double mantissa.  */
184a26ab1d9Smartynas 
185a26ab1d9Smartynas #define GET_LDOUBLE_MSW(v,d)					\
186a26ab1d9Smartynas do {								\
187a26ab1d9Smartynas   ieee_extended_shape_type sh_u;				\
188a26ab1d9Smartynas   sh_u.value = (d);						\
189a26ab1d9Smartynas   (v) = sh_u.parts.msw;						\
190a26ab1d9Smartynas } while (0)
191a26ab1d9Smartynas 
192a26ab1d9Smartynas /* Set the more significant 32 bits of a long double mantissa from an int.  */
193a26ab1d9Smartynas 
194a26ab1d9Smartynas #define SET_LDOUBLE_MSW(d,v)					\
195a26ab1d9Smartynas do {								\
196a26ab1d9Smartynas   ieee_extended_shape_type sh_u;				\
197a26ab1d9Smartynas   sh_u.value = (d);						\
198a26ab1d9Smartynas   sh_u.parts.msw = (v);						\
199a26ab1d9Smartynas   (d) = sh_u.value;						\
200a26ab1d9Smartynas } while (0)
201a26ab1d9Smartynas 
202a26ab1d9Smartynas /* Get int from the exponent of a long double.  */
203a26ab1d9Smartynas 
20449393c00Smartynas #define GET_LDOUBLE_EXP(se,d)					\
205a26ab1d9Smartynas do {								\
206a26ab1d9Smartynas   ieee_extended_shape_type ge_u;				\
207a26ab1d9Smartynas   ge_u.value = (d);						\
20849393c00Smartynas   (se) = ge_u.parts.exp;					\
209a26ab1d9Smartynas } while (0)
210a26ab1d9Smartynas 
211a26ab1d9Smartynas /* Set exponent of a long double from an int.  */
212a26ab1d9Smartynas 
21349393c00Smartynas #define SET_LDOUBLE_EXP(d,se)					\
214a26ab1d9Smartynas do {								\
215a26ab1d9Smartynas   ieee_extended_shape_type se_u;				\
216a26ab1d9Smartynas   se_u.value = (d);						\
21749393c00Smartynas   se_u.parts.exp = (se);					\
218a26ab1d9Smartynas   (d) = se_u.value;						\
219a26ab1d9Smartynas } while (0)
220a26ab1d9Smartynas 
221df930be7Sderaadt /* A union which permits us to convert between a double and two 32 bit
222df930be7Sderaadt    ints.  */
223df930be7Sderaadt 
2245ca6b847Sderaadt /*
22580626675Smartynas  * The arm port is little endian except for the FP word order which is
2265ca6b847Sderaadt  * big endian.
2275ca6b847Sderaadt  */
2285ca6b847Sderaadt 
229016765a7Smartynas #if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
230df930be7Sderaadt 
231df930be7Sderaadt typedef union
232df930be7Sderaadt {
233df930be7Sderaadt   double value;
234df930be7Sderaadt   struct
235df930be7Sderaadt   {
236df930be7Sderaadt     u_int32_t msw;
237df930be7Sderaadt     u_int32_t lsw;
238df930be7Sderaadt   } parts;
239df930be7Sderaadt } ieee_double_shape_type;
240df930be7Sderaadt 
241df930be7Sderaadt #endif
242df930be7Sderaadt 
243016765a7Smartynas #if (BYTE_ORDER == LITTLE_ENDIAN) && !(defined(__arm__) && !defined(__VFP_FP__))
244df930be7Sderaadt 
245df930be7Sderaadt typedef union
246df930be7Sderaadt {
247df930be7Sderaadt   double value;
248df930be7Sderaadt   struct
249df930be7Sderaadt   {
250df930be7Sderaadt     u_int32_t lsw;
251df930be7Sderaadt     u_int32_t msw;
252df930be7Sderaadt   } parts;
253df930be7Sderaadt } ieee_double_shape_type;
254df930be7Sderaadt 
255df930be7Sderaadt #endif
256df930be7Sderaadt 
257df930be7Sderaadt /* Get two 32 bit ints from a double.  */
258df930be7Sderaadt 
259df930be7Sderaadt #define EXTRACT_WORDS(ix0,ix1,d)				\
260df930be7Sderaadt do {								\
261df930be7Sderaadt   ieee_double_shape_type ew_u;					\
262df930be7Sderaadt   ew_u.value = (d);						\
263df930be7Sderaadt   (ix0) = ew_u.parts.msw;					\
264df930be7Sderaadt   (ix1) = ew_u.parts.lsw;					\
265df930be7Sderaadt } while (0)
266df930be7Sderaadt 
267df930be7Sderaadt /* Get the more significant 32 bit int from a double.  */
268df930be7Sderaadt 
269df930be7Sderaadt #define GET_HIGH_WORD(i,d)					\
270df930be7Sderaadt do {								\
271df930be7Sderaadt   ieee_double_shape_type gh_u;					\
272df930be7Sderaadt   gh_u.value = (d);						\
273df930be7Sderaadt   (i) = gh_u.parts.msw;						\
274df930be7Sderaadt } while (0)
275df930be7Sderaadt 
276df930be7Sderaadt /* Get the less significant 32 bit int from a double.  */
277df930be7Sderaadt 
278df930be7Sderaadt #define GET_LOW_WORD(i,d)					\
279df930be7Sderaadt do {								\
280df930be7Sderaadt   ieee_double_shape_type gl_u;					\
281df930be7Sderaadt   gl_u.value = (d);						\
282df930be7Sderaadt   (i) = gl_u.parts.lsw;						\
283df930be7Sderaadt } while (0)
284df930be7Sderaadt 
285df930be7Sderaadt /* Set a double from two 32 bit ints.  */
286df930be7Sderaadt 
287df930be7Sderaadt #define INSERT_WORDS(d,ix0,ix1)					\
288df930be7Sderaadt do {								\
289df930be7Sderaadt   ieee_double_shape_type iw_u;					\
290df930be7Sderaadt   iw_u.parts.msw = (ix0);					\
291df930be7Sderaadt   iw_u.parts.lsw = (ix1);					\
292df930be7Sderaadt   (d) = iw_u.value;						\
293df930be7Sderaadt } while (0)
294df930be7Sderaadt 
295df930be7Sderaadt /* Set the more significant 32 bits of a double from an int.  */
296df930be7Sderaadt 
297df930be7Sderaadt #define SET_HIGH_WORD(d,v)					\
298df930be7Sderaadt do {								\
299df930be7Sderaadt   ieee_double_shape_type sh_u;					\
300df930be7Sderaadt   sh_u.value = (d);						\
301df930be7Sderaadt   sh_u.parts.msw = (v);						\
302df930be7Sderaadt   (d) = sh_u.value;						\
303df930be7Sderaadt } while (0)
304df930be7Sderaadt 
305df930be7Sderaadt /* Set the less significant 32 bits of a double from an int.  */
306df930be7Sderaadt 
307df930be7Sderaadt #define SET_LOW_WORD(d,v)					\
308df930be7Sderaadt do {								\
309df930be7Sderaadt   ieee_double_shape_type sl_u;					\
310df930be7Sderaadt   sl_u.value = (d);						\
311df930be7Sderaadt   sl_u.parts.lsw = (v);						\
312df930be7Sderaadt   (d) = sl_u.value;						\
313df930be7Sderaadt } while (0)
314df930be7Sderaadt 
315df930be7Sderaadt /* A union which permits us to convert between a float and a 32 bit
316df930be7Sderaadt    int.  */
317df930be7Sderaadt 
318df930be7Sderaadt typedef union
319df930be7Sderaadt {
320df930be7Sderaadt   float value;
321df930be7Sderaadt   u_int32_t word;
322df930be7Sderaadt } ieee_float_shape_type;
323df930be7Sderaadt 
324df930be7Sderaadt /* Get a 32 bit int from a float.  */
325df930be7Sderaadt 
326df930be7Sderaadt #define GET_FLOAT_WORD(i,d)					\
327df930be7Sderaadt do {								\
328df930be7Sderaadt   ieee_float_shape_type gf_u;					\
329df930be7Sderaadt   gf_u.value = (d);						\
330df930be7Sderaadt   (i) = gf_u.word;						\
331df930be7Sderaadt } while (0)
332df930be7Sderaadt 
333df930be7Sderaadt /* Set a float from a 32 bit int.  */
334df930be7Sderaadt 
335df930be7Sderaadt #define SET_FLOAT_WORD(d,i)					\
336df930be7Sderaadt do {								\
337df930be7Sderaadt   ieee_float_shape_type sf_u;					\
338df930be7Sderaadt   sf_u.word = (i);						\
339df930be7Sderaadt   (d) = sf_u.value;						\
340df930be7Sderaadt } while (0)
341df930be7Sderaadt 
342eac90eaaSmartynas #ifdef FLT_EVAL_METHOD
343eac90eaaSmartynas /*
344eac90eaaSmartynas  * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
345eac90eaaSmartynas  */
346eac90eaaSmartynas #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
347eac90eaaSmartynas #define	STRICT_ASSIGN(type, lval, rval)	((lval) = (rval))
348390c8400Smartynas #else /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */
349eac90eaaSmartynas #define	STRICT_ASSIGN(type, lval, rval) do {	\
350eac90eaaSmartynas 	volatile type __lval;			\
351eac90eaaSmartynas 						\
3523609bd3bSkettenis 	if (sizeof(type) >= sizeof(long double))	\
353eac90eaaSmartynas 		(lval) = (rval);		\
354eac90eaaSmartynas 	else {					\
355eac90eaaSmartynas 		__lval = (rval);		\
356eac90eaaSmartynas 		(lval) = __lval;		\
357eac90eaaSmartynas 	}					\
358eac90eaaSmartynas } while (0)
359390c8400Smartynas #endif /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */
360390c8400Smartynas #endif /* FLT_EVAL_METHOD */
361eac90eaaSmartynas 
362*2f2c0062Sguenther __BEGIN_HIDDEN_DECLS
363df930be7Sderaadt /* fdlibm kernel function */
3647b36286aSmartynas extern int    __ieee754_rem_pio2(double,double*);
365c72b5b24Smillert extern double __kernel_sin(double,double,int);
366c72b5b24Smillert extern double __kernel_cos(double,double);
367c72b5b24Smillert extern double __kernel_tan(double,double,int);
368390c8400Smartynas extern int    __kernel_rem_pio2(double*,double*,int,int,int);
369df930be7Sderaadt 
370df930be7Sderaadt /* float versions of fdlibm kernel functions */
3717b36286aSmartynas extern int   __ieee754_rem_pio2f(float,float*);
372c72b5b24Smillert extern float __kernel_sinf(float,float,int);
373c72b5b24Smillert extern float __kernel_cosf(float,float);
374c72b5b24Smillert extern float __kernel_tanf(float,float,int);
375c72b5b24Smillert extern int   __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
376df930be7Sderaadt 
377390c8400Smartynas /* long double precision kernel functions */
378390c8400Smartynas long double __kernel_sinl(long double, long double, int);
379390c8400Smartynas long double __kernel_cosl(long double, long double);
380390c8400Smartynas long double __kernel_tanl(long double, long double, int);
381390c8400Smartynas 
382390c8400Smartynas /*
383390c8400Smartynas  * Common routine to process the arguments to nan(), nanf(), and nanl().
384390c8400Smartynas  */
385390c8400Smartynas void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
386*2f2c0062Sguenther __END_HIDDEN_DECLS
387390c8400Smartynas 
3885b14c9c6Smartynas /*
3895b14c9c6Smartynas  * TRUNC() is a macro that sets the trailing 27 bits in the mantissa
3905b14c9c6Smartynas  * of an IEEE double variable to zero.  It must be expression-like
3915b14c9c6Smartynas  * for syntactic reasons, and we implement this expression using
3925b14c9c6Smartynas  * an inline function instead of a pure macro to avoid depending
3935b14c9c6Smartynas  * on the gcc feature of statement-expressions.
3945b14c9c6Smartynas  */
3955b14c9c6Smartynas #define TRUNC(d)	(_b_trunc(&(d)))
3965b14c9c6Smartynas 
3975b14c9c6Smartynas static __inline void
_b_trunc(volatile double * _dp)3985b14c9c6Smartynas _b_trunc(volatile double *_dp)
3995b14c9c6Smartynas {
4005b14c9c6Smartynas 	uint32_t _lw;
4015b14c9c6Smartynas 
4025b14c9c6Smartynas 	GET_LOW_WORD(_lw, *_dp);
4035b14c9c6Smartynas 	SET_LOW_WORD(*_dp, _lw & 0xf8000000);
4045b14c9c6Smartynas }
4055b14c9c6Smartynas 
4065b14c9c6Smartynas struct Double {
4075b14c9c6Smartynas 	double	a;
4085b14c9c6Smartynas 	double	b;
4095b14c9c6Smartynas };
4105b14c9c6Smartynas 
4115b14c9c6Smartynas /*
4125b14c9c6Smartynas  * Functions internal to the math package, yet not static.
4135b14c9c6Smartynas  */
414*2f2c0062Sguenther __BEGIN_HIDDEN_DECLS
4155b14c9c6Smartynas double __exp__D(double, double);
4165b14c9c6Smartynas struct Double __log__D(double);
41712129755Smartynas long double __p1evll(long double, void *, int);
41812129755Smartynas long double __polevll(long double, void *, int);
419*2f2c0062Sguenther __END_HIDDEN_DECLS
4205b14c9c6Smartynas 
421df930be7Sderaadt #endif /* _MATH_PRIVATE_H_ */
422