Home | History | Annotate | Line # | Download | only in libf7
libf7.h revision 1.1.1.2
      1 /* Copyright (C) 2019-2022 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
    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
    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
    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
    180 bool f7_class_nan (uint8_t c)
    181 {
    182   return c & F7_FLAG_nan;
    183 }
    184 
    185 static F7_INLINE
    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
    193 bool f7_class_number (uint8_t c)
    194 {
    195   return c <= (F7_FLAG_sign | F7_FLAG_zero);
    196 }
    197 
    198 static F7_INLINE
    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
    206 bool f7_class_zero (uint8_t c)
    207 {
    208   return c & F7_FLAG_zero;
    209 }
    210 
    211 static F7_INLINE
    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
    219 bool f7_class_nonzero (uint8_t c)
    220 {
    221   return c <= F7_FLAG_sign;
    222 }
    223 
    224 static F7_INLINE
    225 bool f7_is_nonzero (const f7_t *aa)
    226 {
    227   return f7_class_nonzero (f7_classify (aa));
    228 }
    229 
    230 static F7_INLINE
    231 bool f7_class_sign (uint8_t c)
    232 {
    233   return c & F7_FLAG_sign;
    234 }
    235 
    236 static F7_INLINE
    237 bool f7_signbit (const f7_t *aa)
    238 {
    239   return aa->flags & F7_FLAG_sign;
    240 }
    241 
    242 static F7_INLINE
    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
    251 void f7_set_nan (f7_t *cc)
    252 {
    253   cc->flags = F7_FLAG_nan;
    254 }
    255 
    256 static F7_INLINE
    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
    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
    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
    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
    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
    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
    318 bool f7_is0 (const f7_t *aa)
    319 {
    320   return 0 == f7_msbit (aa);
    321 }
    322 
    323 
    324 static F7_INLINE
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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