1 /* Copyright (C) 2019-2020 Free Software Foundation, Inc.
2 
3    This file is part of LIBF7, which is part of GCC.
4 
5    GCC is free software; you can redistribute it and/or modify it under
6    the terms of the GNU General Public License as published by the Free
7    Software Foundation; either version 3, or (at your option) any later
8    version.
9 
10    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11    WARRANTY; without even the implied warranty of MERCHANTABILITY or
12    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13    for more details.
14 
15    Under Section 7 of GPL version 3, you are granted additional
16    permissions described in the GCC Runtime Library Exception, version
17    3.1, as published by the Free Software Foundation.
18 
19    You should have received a copy of the GNU General Public License and
20    a copy of the GCC Runtime Library Exception along with this program;
21    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22    <http://www.gnu.org/licenses/>.  */
23 
24 #ifndef LIBF7_H
25 #define LIBF7_H
26 #define IN_LIBF7_H
27 
28 #include "f7-renames.h"
29 
30 #define F7_MANT_BYTES 7
31 #define F7_MANT_BITS (8 * F7_MANT_BYTES)
32 
33 /*  Using the following GCC features:
34     --  Unnamed structs / unions (GNU-C)
35     --  Fixed-point types (GNU-C)
36     --  Inline asm
37     --  Setting assembler names by means of __asm (GNU-C).
38     --  Attributes: alias, always_inline, const, noinline, unused,
39                     progmem, pure, weak, warning
40     --  GCC built-ins: __builtin_abort, __builtin_constant_p
41     --  AVR built-ins: __builtin_avr_bitsr, __builtin_avr_rbits
42 */
43 
44 /* We have 2 kinds of flags:
45 
46    A)  The flags that are stored in f7_t.flags:
47        --  f7_t.is_nan (NaN)
48        --  f7_t.is_inf (+Inf or -Inf)
49        --  f7_t.sign (negative or -Inf).
50 
51    B)  The flags that are returned by f7_classify().  This are the
52        flags from A) together with
53        --  _zero: indicate that a number is zero.
54 */
55 
56 #define F7_FLAGNO_sign  0
57 #define F7_FLAGNO_zero  1
58 #define F7_FLAGNO_nan   2
59 #define F7_FLAGNO_inf   7
60 
61 #define F7_HAVE_Inf 1
62 
63 // Flags that might be set by f7_classify().
64 #define F7_FLAG_sign            (1 << F7_FLAGNO_sign)
65 #define F7_FLAG_zero            (1 << F7_FLAGNO_zero)
66 #define F7_FLAG_nan             (1 << F7_FLAGNO_nan)
67 #define F7_FLAG_inf   (F7_HAVE_Inf << F7_FLAGNO_inf)
68 
69 // Flags that might be set in f7_t.flags.
70 #define F7_FLAGS (F7_FLAG_inf | F7_FLAG_nan | F7_FLAG_sign)
71 
72 #if !defined __ASSEMBLER__
73 
74 #ifndef IN_LIBGCC2
75 #include <stdint.h>
76 #include <stdbool.h>
77 #include <stdlib.h>
78 #include <stdio.h>
79 #else
80 /* Do not assume that we have std headers when we build libgcc.  */
81 
82 typedef __UINT64_TYPE__ uint64_t;
83 typedef __UINT32_TYPE__ uint32_t;
84 typedef __UINT16_TYPE__ uint16_t;
85 typedef __UINT8_TYPE__  uint8_t;
86 typedef __INT64_TYPE__ int64_t;
87 typedef __INT32_TYPE__ int32_t;
88 typedef __INT16_TYPE__ int16_t;
89 typedef __INT8_TYPE__  int8_t;
90 typedef _Bool bool;
91 #define false 0
92 #define true  1
93 #define INT8_MIN  (-1 - __INT8_MAX__)
94 #define INT16_MAX __INT16_MAX__
95 #define NULL ((void*) 0)
96 #endif /* IN_LIBGCC2 */
97 
98 #include "asm-defs.h"
99 
100 #ifdef __cplusplus
101 extern "C" {
102 #define _Static_assert(X, Y) static_assert (X)
103 #endif // C++
104 
105 #define F7_INLINE   inline __attribute__((__always_inline__))
106 #define F7_NOINLINE __attribute__((__noinline__))
107 #define F7_WEAK     __attribute__((__weak__))
108 #define F7_PURE     __attribute__((__pure__))
109 #define F7_UNUSED   __attribute__((__unused__))
110 #define F7_CONST    __attribute__((__const__))
111 
112 #define F7_STRINGY2(X)  #X
113 #define F7_STRINGY(X)   F7_STRINGY2(X)
114 #define F7ASM(X)        __asm (F7_STRINGY2(X))
115 
116 typedef struct f7_t
117 {
118   union
119   {
120     struct
121     {
122       uint8_t sign        :1;
123       uint8_t reserved1   :1;
124       uint8_t is_nan      :1;
125       uint8_t reserved2   :4;
126       uint8_t is_inf      :1;
127     };
128     uint8_t flags;
129   };
130 
131   uint8_t mant[7];
132   int16_t expo;
133 } f7_t;
134 
135 typedef uint64_t f7_double_t;
136 
137 #define F7_MANT_HI4(X) \
138   (*(uint32_t*) & (X)->mant[F7_MANT_BYTES - 4])
139 
140 #define F7_MANT_CONST_HI4(X) \
141   (*(const uint32_t*) & (X)->mant[F7_MANT_BYTES - 4])
142 
143 #define F7_MANT_HI2(X) \
144   (*(uint16_t*) & (X)->mant[F7_MANT_BYTES - 2])
145 
146 static F7_INLINE F7_PURE
f7_classify(const f7_t * aa)147 uint8_t f7_classify (const f7_t *aa)
148 {
149   extern void f7_classify_asm (void);
150   register uint8_t rclass __asm ("r24");
151   __asm ("%~call %x[f]"
152 	 : "=r" (rclass)
153 	 : [f] "i" (f7_classify_asm), "z" (aa));
154   return rclass;
155 }
156 
157 
158 // +Inf or -Inf
159 static F7_INLINE
f7_class_inf(uint8_t c)160 bool f7_class_inf (uint8_t c)
161 {
162 #if defined (F7_HAVE_Inf) && F7_HAVE_Inf == 1
163   return c >= F7_FLAG_inf;
164 #elif defined (F7_HAVE_Inf) && F7_HAVE_Inf == 0
165   (void) c;
166   return false;
167 #else
168 #error macro F7_HAVE_Inf must be defined to 0 or to 1.
169 #endif // Have Inf
170 }
171 
172 static F7_INLINE
f7_is_inf(const f7_t * aa)173 bool f7_is_inf (const f7_t *aa)
174 {
175   return f7_class_inf (aa->flags);
176 }
177 
178 // Not-a-Number (NaN).
179 static F7_INLINE
f7_class_nan(uint8_t c)180 bool f7_class_nan (uint8_t c)
181 {
182   return c & F7_FLAG_nan;
183 }
184 
185 static F7_INLINE
f7_is_nan(const f7_t * aa)186 bool f7_is_nan (const f7_t *aa)
187 {
188   return f7_class_nan (aa->flags);
189 }
190 
191 // Some number
192 static F7_INLINE
f7_class_number(uint8_t c)193 bool f7_class_number (uint8_t c)
194 {
195   return c <= (F7_FLAG_sign | F7_FLAG_zero);
196 }
197 
198 static F7_INLINE
f7_is_number(const f7_t * aa)199 bool f7_is_number (const f7_t *aa)
200 {
201   return f7_class_number (f7_classify (aa));
202 }
203 
204 // Zero
205 static F7_INLINE
f7_class_zero(uint8_t c)206 bool f7_class_zero (uint8_t c)
207 {
208   return c & F7_FLAG_zero;
209 }
210 
211 static F7_INLINE
f7_is_zero(const f7_t * aa)212 bool f7_is_zero (const f7_t *aa)
213 {
214   return f7_class_zero (f7_classify (aa));
215 }
216 
217 // A non-zero number.
218 static F7_INLINE
f7_class_nonzero(uint8_t c)219 bool f7_class_nonzero (uint8_t c)
220 {
221   return c <= F7_FLAG_sign;
222 }
223 
224 static F7_INLINE
f7_is_nonzero(const f7_t * aa)225 bool f7_is_nonzero (const f7_t *aa)
226 {
227   return f7_class_nonzero (f7_classify (aa));
228 }
229 
230 static F7_INLINE
f7_class_sign(uint8_t c)231 bool f7_class_sign (uint8_t c)
232 {
233   return c & F7_FLAG_sign;
234 }
235 
236 static F7_INLINE
f7_signbit(const f7_t * aa)237 bool f7_signbit (const f7_t *aa)
238 {
239   return aa->flags & F7_FLAG_sign;
240 }
241 
242 static F7_INLINE
f7_set_sign(f7_t * cc,bool sign)243 void f7_set_sign (f7_t *cc, bool sign)
244 {
245   _Static_assert (F7_FLAGNO_sign == 0, "");
246   cc->flags &= ~F7_FLAG_sign;
247   cc->flags |= sign;
248 }
249 
250 static F7_INLINE
f7_set_nan(f7_t * cc)251 void f7_set_nan (f7_t *cc)
252 {
253   cc->flags = F7_FLAG_nan;
254 }
255 
256 static F7_INLINE
f7_clr(f7_t * cc)257 void f7_clr (f7_t *cc)
258 {
259   extern void f7_clr_asm (void);
260   __asm ("%~call %x[f]"
261 	 :
262 	 : [f] "i" (f7_clr_asm), "z" (cc)
263 	 : "memory");
264 }
265 
266 static F7_INLINE
f7_copy(f7_t * cc,const f7_t * aa)267 f7_t* f7_copy (f7_t *cc, const f7_t *aa)
268 {
269   extern void f7_copy_asm (void);
270   __asm ("%~call %x[f]"
271 	 :
272 	 : [f] "i" (f7_copy_asm), "z" (cc), "x" (aa)
273 	 : "memory");
274   return cc;
275 }
276 
277 static F7_INLINE
f7_copy_P(f7_t * cc,const f7_t * aa)278 f7_t* f7_copy_P (f7_t *cc, const f7_t *aa)
279 {
280   extern void f7_copy_P_asm (void);
281   __asm ("%~call %x[f]"
282 	 :
283 	 : [f] "i" (f7_copy_P_asm), "x" (cc), "z" (aa)
284 	 : "memory");
285   return cc;
286 }
287 
288 static F7_INLINE
f7_copy_mant(f7_t * cc,const f7_t * aa)289 void f7_copy_mant (f7_t *cc, const f7_t *aa)
290 {
291   extern void f7_copy_mant_asm (void);
292   __asm ("%~call %x[f]"
293 	 :
294 	 : [f] "i" (f7_copy_mant_asm), "z" (cc), "x" (aa)
295 	 : "memory");
296 }
297 
298 static F7_INLINE
f7_set_inf(f7_t * cc,bool sign)299 void f7_set_inf (f7_t *cc, bool sign)
300 {
301 #if F7_HAVE_Inf == 1
302   cc->flags = F7_FLAG_inf | sign;
303 #else
304   (void) sign;
305   cc->flags = F7_FLAG_nan;
306 #endif // Have Inf
307 }
308 
309 
310 static F7_INLINE
f7_msbit(const f7_t * aa)311 bool f7_msbit (const f7_t *aa)
312 {
313   return aa->mant[F7_MANT_BYTES - 1] & 0x80;
314 }
315 
316 // Quick test against 0 if A is known to be a number (neither NaN nor Inf).
317 static F7_INLINE
f7_is0(const f7_t * aa)318 bool f7_is0 (const f7_t *aa)
319 {
320   return 0 == f7_msbit (aa);
321 }
322 
323 
324 static F7_INLINE
f7_cmp_mant(const f7_t * aa,const f7_t * bb)325 int8_t f7_cmp_mant (const f7_t *aa, const f7_t *bb)
326 {
327   extern void f7_cmp_mant_asm (void);
328   register int8_t r24 __asm ("r24");
329   __asm ("%~call %x[f] ;; %1 %3"
330 	 : "=r" (r24)
331 	 : [f] "i" (f7_cmp_mant_asm), "x" (aa), "z" (bb));
332   return r24;
333 }
334 
335 static F7_INLINE
f7_store_expo(f7_t * cc,int16_t expo)336 bool f7_store_expo (f7_t *cc, int16_t expo)
337 {
338   extern void f7_store_expo_asm (void);
339   register bool r24 __asm ("r24");
340   register int16_t rexpo __asm ("r24") = expo;
341   __asm ("%~call %x[f] ;; %0 %2 %3"
342 	 : "=r" (r24)
343 	 : [f] "i" (f7_store_expo_asm), "z" (cc), "r" (rexpo));
344   return r24;
345 }
346 
347 static F7_INLINE
f7_abs(f7_t * cc,const f7_t * aa)348 f7_t* f7_abs (f7_t *cc, const f7_t *aa)
349 {
350   f7_copy (cc, aa);
351   f7_set_sign (cc, 0);
352 
353   return cc;
354 }
355 
356 
357 F7_PURE extern int8_t f7_cmp (const f7_t*, const f7_t*);
358 F7_PURE extern bool f7_lt_impl (const f7_t*, const f7_t*);
359 F7_PURE extern bool f7_le_impl (const f7_t*, const f7_t*);
360 F7_PURE extern bool f7_gt_impl (const f7_t*, const f7_t*);
361 F7_PURE extern bool f7_ge_impl (const f7_t*, const f7_t*);
362 F7_PURE extern bool f7_ne_impl (const f7_t*, const f7_t*);
363 F7_PURE extern bool f7_eq_impl (const f7_t*, const f7_t*);
364 F7_PURE extern bool f7_unord_impl (const f7_t*, const f7_t*);
365 
366 static F7_INLINE
f7_lt(const f7_t * aa,const f7_t * bb)367 bool f7_lt (const f7_t *aa, const f7_t *bb)
368 {
369   return 2 & f7_cmp (aa, bb);
370 }
371 
372 static F7_INLINE
f7_gt(const f7_t * aa,const f7_t * bb)373 bool f7_gt (const f7_t *aa, const f7_t *bb)
374 {
375   return 1 == f7_cmp (aa, bb);
376 }
377 
378 static F7_INLINE
f7_le(const f7_t * aa,const f7_t * bb)379 bool f7_le (const f7_t *aa, const f7_t *bb)
380 {
381   int8_t c = f7_cmp (aa, bb);
382   return (uint8_t) (c + 1) <= 1;
383 }
384 
385 static F7_INLINE
f7_ge(const f7_t * aa,const f7_t * bb)386 bool f7_ge (const f7_t *aa, const f7_t *bb)
387 {
388   return f7_cmp (aa, bb) >= 0;
389 }
390 
391 static F7_INLINE
f7_unordered(const f7_t * aa,const f7_t * bb)392 bool f7_unordered (const f7_t *aa, const f7_t *bb)
393 {
394   return INT8_MIN == f7_cmp (aa, bb);
395 }
396 
397 static F7_INLINE
f7_ordered(const f7_t * aa,const f7_t * bb)398 bool f7_ordered (const f7_t *aa, const f7_t *bb)
399 {
400   return INT8_MIN != f7_cmp (aa, bb);
401 }
402 
403 static F7_INLINE
f7_eq(const f7_t * aa,const f7_t * bb)404 bool f7_eq (const f7_t *aa, const f7_t *bb)
405 {
406   return 0 == f7_cmp (aa, bb);
407 }
408 
409 static F7_INLINE
f7_ne(const f7_t * aa,const f7_t * bb)410 bool f7_ne (const f7_t *aa, const f7_t *bb)
411 {
412   return 1 & f7_cmp (aa, bb);
413 }
414 
415 extern void f7_clr (f7_t*);
416 
417 __attribute__((warning ("foo_u16"))) void foo_u16 (void);
418 __attribute__((warning ("foo_s16"))) void foo_s16 (void);
419 
420 extern f7_t* f7_set_s16_impl (f7_t*, int16_t);
421 extern f7_t* f7_set_u16_impl (f7_t*, uint16_t);
422 
423 static F7_INLINE
f7_set_u16_worker(f7_t * cc,uint16_t u16)424 f7_t* f7_set_u16_worker (f7_t *cc, uint16_t u16)
425 {
426   if (__builtin_constant_p (u16))
427     {
428       if (u16 == 0)
429 	return cc;
430 
431       uint8_t off = __builtin_clz (u16);
432       if (15 - off)
433 	* (uint8_t*) & cc->expo = (uint8_t) (15 - off);
434       u16 <<= off;
435       if (u16 & 0xff)
436 	cc->mant[5] = (uint8_t) u16;
437       if (u16 & 0xff00)
438 	cc->mant[6] = (uint8_t) (u16 >> 8);
439 
440       return cc;
441     }
442   else
443     {
444       foo_u16();
445       __builtin_abort();
446       return NULL;
447     }
448 }
449 
450 static F7_INLINE
f7_set_u16(f7_t * cc,uint16_t u16)451 f7_t* f7_set_u16 (f7_t *cc, uint16_t u16)
452 {
453   if (__builtin_constant_p (u16))
454     {
455       f7_clr (cc);
456       return f7_set_u16_worker (cc, u16);
457     }
458 
459   return f7_set_u16_impl (cc, u16);
460 }
461 
462 static F7_INLINE
f7_set_s16(f7_t * cc,int16_t s16)463 f7_t* f7_set_s16 (f7_t *cc, int16_t s16)
464 {
465   if (__builtin_constant_p (s16))
466     {
467       f7_clr (cc);
468 
469       uint16_t u16 = (uint16_t) s16;
470 
471       if (s16 < 0)
472         {
473 	  u16 = -u16;
474 	  cc->flags = F7_FLAG_sign;
475         }
476 
477       return f7_set_u16_worker (cc, u16);
478     }
479 
480   return f7_set_s16_impl (cc, s16);
481 }
482 
483 static F7_INLINE
f7_set_eps(f7_t * cc,uint8_t eps,bool sign)484 void f7_set_eps (f7_t *cc, uint8_t eps, bool sign)
485 {
486   cc = f7_set_u16 (cc, 1);
487   if (!__builtin_constant_p (sign) || sign)
488     cc->flags = sign;
489   cc->mant[0] = eps;
490 }
491 
492 static F7_INLINE
f7_set_1pow2(f7_t * cc,int16_t expo,bool sign)493 f7_t* f7_set_1pow2 (f7_t *cc, int16_t expo, bool sign)
494 {
495   cc = f7_set_u16 (cc, 1);
496   cc->expo = expo;
497   if (!__builtin_constant_p (sign) || sign)
498     cc->flags = sign;
499   return cc;
500 }
501 
502 static F7_INLINE
f7_set_u64(f7_t * cc,uint64_t u64)503 f7_t* f7_set_u64 (f7_t *cc, uint64_t u64)
504 {
505   extern f7_t* f7_set_u64_asm (uint64_t, f7_t*);
506   return f7_set_u64_asm (u64, cc);
507 }
508 
509 static F7_INLINE
f7_set_s64(f7_t * cc,int64_t s64)510 f7_t* f7_set_s64 (f7_t *cc, int64_t s64)
511 {
512   extern f7_t* f7_set_s64_asm (int64_t, f7_t*);
513   return f7_set_s64_asm (s64, cc);
514 }
515 
516 extern void f7_set_double_impl (f7_double_t, f7_t*);
517 static F7_INLINE
f7_set_double(f7_t * cc,f7_double_t val64)518 void f7_set_double (f7_t *cc, f7_double_t val64)
519 {
520   f7_set_double_impl (val64, cc);
521 }
522 
523 extern f7_t* f7_init_impl (uint64_t, uint8_t, f7_t*, int16_t);
524 
525 static F7_INLINE
f7_init(f7_t * cc,uint8_t flags,uint64_t mant,int16_t expo)526 f7_t* f7_init (f7_t *cc, uint8_t flags, uint64_t mant, int16_t expo)
527 {
528   return f7_init_impl (mant, flags, cc, expo);
529 }
530 
531 extern f7_t* f7_set_s32 (f7_t*, int32_t);
532 extern f7_t* f7_set_u16 (f7_t*, uint16_t);
533 extern f7_t* f7_set_u32 (f7_t*, uint32_t);
534 extern void f7_set_float (f7_t*, float);
535 extern void f7_set_pdouble (f7_t*, const f7_double_t*);
536 
537 F7_PURE extern int16_t f7_get_s16 (const f7_t*);
538 F7_PURE extern int32_t f7_get_s32 (const f7_t*);
539 F7_PURE extern int64_t f7_get_s64 (const f7_t*);
540 F7_PURE extern uint16_t f7_get_u16 (const f7_t*);
541 F7_PURE extern uint32_t f7_get_u32 (const f7_t*);
542 F7_PURE extern uint64_t f7_get_u64 (const f7_t*);
543 F7_PURE extern float f7_get_float (const f7_t*);
544 F7_PURE extern f7_double_t f7_get_double (const f7_t*);
545 
546 #if USE_LPM == 1
547   #define F7_PGMSPACE     __attribute__((__progmem__))
548   #define f7_copy_flash   f7_copy_P
549 
550   #define f7_const(X, NAME) \
551     f7_copy_P ((X), & F7_(const_ ## NAME ## _P))
552 
553   #define F7_CONST_DEF(NAME, FLAGS, M0, M1, M2, M3, M4, M5, M6, EXPO) \
554     extern const f7_t F7_(const_ ## NAME ## _P);
555   #include "libf7-const.def"
556   #undef F7_CONST_DEF
557 #else
558   #define F7_PGMSPACE     // Empty
559   #define f7_copy_flash   f7_copy
560 
561   #define f7_const(X, NAME) \
562     f7_copy ((X), & F7_(const_ ## NAME))
563 
564   #define F7_CONST_DEF(NAME, FLAGS, M0, M1, M2, M3, M4, M5, M6, EXPO) \
565     extern const f7_t F7_(const_ ## NAME);
566   #include "libf7-const.def"
567   #undef F7_CONST_DEF
568 #endif // USE_LPM
569 
570 
571 // Basic floating point arithmetic:
572 // double output <=> f7_t*
573 // double input  <=> const f7_t*
574 extern f7_t* f7_neg (f7_t*, const f7_t*);
575 extern void f7_add (f7_t*, const f7_t*, const f7_t*);
576 extern void f7_sub (f7_t*, const f7_t*, const f7_t*);
577 extern void f7_mul (f7_t*, const f7_t*, const f7_t*);
578 extern void f7_div (f7_t*, const f7_t*, const f7_t*);
579 
580 // Analogies of functions from math.h:
581 // double output <=> f7_t*
582 // double input  <=> const f7_t*
583 extern void f7_fabs (f7_t*, const f7_t*);
584 extern void f7_fmod (f7_t*, const f7_t*, const f7_t*);
585 extern void f7_frexp (f7_t*, const f7_t*, int*);
586 extern void f7_exp (f7_t*, const f7_t*);
587 extern void f7_log (f7_t*, const f7_t*);
588 extern void f7_pow (f7_t*, const f7_t*, const f7_t*);
589 extern void f7_sqrt (f7_t*, const f7_t*);
590 extern void f7_cbrt (f7_t*, const f7_t*);
591 extern void f7_hypot (f7_t*, const f7_t*, const f7_t*);
592 extern f7_t* f7_ldexp (f7_t*, const f7_t*, int);
593 extern f7_t* f7_fmax (f7_t*, const f7_t*, const f7_t*);
594 extern f7_t* f7_fmin (f7_t*, const f7_t*, const f7_t*);
595 extern f7_t* f7_trunc (f7_t*, const f7_t*);
596 extern f7_t* f7_floor (f7_t*, const f7_t*);
597 extern void f7_ceil (f7_t*, const f7_t*);
598 extern void f7_round (f7_t*, const f7_t*);
599 extern void f7_sin (f7_t*, const f7_t*);
600 extern void f7_cos (f7_t*, const f7_t*);
601 extern void f7_tan (f7_t*, const f7_t*);
602 extern void f7_atan (f7_t*, const f7_t*);
603 extern void f7_asin (f7_t*, const f7_t*);
604 extern void f7_acos (f7_t*, const f7_t*);
605 extern void f7_tanh (f7_t*, const f7_t*);
606 extern void f7_sinh (f7_t*, const f7_t*);
607 extern void f7_cosh (f7_t*, const f7_t*);
608 extern void f7_log2 (f7_t*, const f7_t*);
609 extern void f7_log10 (f7_t*, const f7_t*);
610 extern void f7_exp10 (f7_t*, const f7_t*);
611 extern void f7_pow10 (f7_t*, const f7_t*);
612 
613 // Just prototypes, not implemented yet.
614 extern void f7_atan2 (f7_t*, const f7_t*, const f7_t*);
615 extern long f7_lrint (const f7_t*);
616 extern long f7_lround (const f7_t*);
617 
618 // Helper functions, aliases, convenience.
619 extern void f7_div1 (f7_t*, const f7_t*);
620 extern void f7_square (f7_t*, const f7_t*);
621 
622 extern void f7_powi (f7_t*, const f7_t*, int);
623 extern f7_t* f7_max (f7_t*, const f7_t*, const f7_t*);
624 extern f7_t* f7_min (f7_t*, const f7_t*, const f7_t*);
625 extern f7_t* f7_truncx (f7_t*, const f7_t*, bool);
626 extern void f7_cotan (f7_t*, const f7_t*);
627 extern void f7_sincos (f7_t*, f7_t*, const f7_t*);
628 extern void f7_asinacos (f7_t*, const f7_t*, uint8_t);
629 extern void f7_sinhcosh (f7_t*, const f7_t*, bool);
630 
631 extern void f7_horner (f7_t*, const f7_t*, uint8_t, const f7_t *coeff, f7_t*);
632 extern void f7_mul_noround (f7_t*, const f7_t*, const f7_t*);
633 extern void f7_clr_mant_lsbs (f7_t*, const f7_t*, uint8_t) F7ASM(f7_clr_mant_lsbs_asm);
634 
635 F7_PURE extern int8_t f7_cmp_unordered (const f7_t*, const f7_t*, bool);
636 F7_PURE extern int8_t f7_cmp_abs (const f7_t*, const f7_t*);
637 
638 F7_PURE extern bool f7_abscmp_msb_ge (const f7_t*, uint8_t msb, int16_t expo);
639 extern void f7_addsub (f7_t*, const f7_t*, const f7_t*, bool neg_b);
640 extern void f7_madd_msub (f7_t*, const f7_t*, const f7_t*, const f7_t*, bool);
641 extern void f7_madd (f7_t*, const f7_t*, const f7_t*, const f7_t*);
642 extern void f7_msub (f7_t*, const f7_t*, const f7_t*, const f7_t*);
643 extern uint8_t f7_mulx (f7_t*, const f7_t*, const f7_t*, bool);
644 extern void f7_divx (f7_t*, const f7_t*, const f7_t*, uint8_t);
645 extern void f7_logx (f7_t*, const f7_t*, const f7_t*);
646 extern f7_t* f7_minmax (f7_t*, const f7_t*, const f7_t*, bool);
647 
648 // Idem:
649 //    f7_Ifunc (y)    = f7_func (y, y)
650 //    f7_Ifunc (y, x) = f7_func (y, y, x)
651 extern void f7_Iadd (f7_t*, const f7_t*);
652 extern void f7_Isub (f7_t*, const f7_t*);
653 extern void f7_Imul (f7_t*, const f7_t*);
654 extern void f7_Idiv (f7_t*, const f7_t*);
655 extern void f7_IRsub (f7_t*, const f7_t*);
656 extern void f7_Ineg (f7_t*);
657 extern void f7_Isqrt (f7_t*);
658 extern void f7_Isquare (f7_t*);
659 extern f7_t* f7_Ildexp (f7_t*, int);
660 
661 // Protoypes for some functions from libf7-asm.sx.
662 F7_CONST extern uint16_t f7_sqrt16_round (uint16_t) F7ASM(f7_sqrt16_round_asm);
663 F7_CONST extern uint8_t  f7_sqrt16_floor (uint16_t) F7ASM(f7_sqrt16_floor_asm);
664 extern void f7_addsub_mant_scaled_asm (f7_t*, const f7_t*, const f7_t*, uint8_t);
665 extern uint8_t f7_mul_mant_asm (f7_t*, const f7_t*, const f7_t*, uint8_t);
666 extern void f7_sqrt_approx_asm (f7_t*, const f7_t*);
667 extern uint64_t f7_lshrdi3 (uint64_t, uint8_t) F7ASM(f7_lshrdi3_asm);
668 extern uint64_t f7_ashldi3 (uint64_t, uint8_t) F7ASM(f7_ashldi3_asm);
669 // Normalize a non-Inf, non-NaN value.  Sets .sign to 0.
670 extern f7_t* f7_normalize_asm (f7_t*);
671 
672 // Dumping.
673 #ifndef IN_LIBGCC2
674 extern void f7_dump (const f7_t*);
675 extern void f7_dump_mant (const f7_t*);
676 extern void f7_put_C (const f7_t*, FILE*);
677 extern void f7_put_CDEF (const char *name, const f7_t*, FILE*);
678 #endif /* IN_LIBGCC2 */
679 
680 #ifdef __cplusplus
681 } // extern "C"
682 #include "libf7-class.h"
683 #endif // C++
684 
685 #endif /* __ASSEMBLER__ */
686 #undef IN_LIBF7_H
687 #endif /* LIBF7_H */
688