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