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