1 /* mpfr_sub1sp1 -- internal function to perform a "real" subtraction on one limb
2    This code was extracted by Kremlin from a formal proof in F*
3    done by Félix Breton in June-July 2019: do not modify it!
4 
5 Source: https://github.com/project-everest/hacl-star/tree/dev_mpfr/code/mpfr
6 
7 Copyright 2004-2020 Free Software Foundation, Inc.
8 Contributed by the AriC and Caramba projects, INRIA.
9 
10 This file is part of the GNU MPFR Library.
11 
12 The GNU MPFR Library is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or (at your
15 option) any later version.
16 
17 The GNU MPFR Library is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
20 License for more details.
21 
22 You should have received a copy of the GNU Lesser General Public License
23 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
24 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
25 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
26 
27 #include "stdint.h"
28 #include "inttypes.h" /* for __builtin_clzll */
29 
30 /* beginning of manually added declarations */
31 
32 #define MPFR_mpfr_sub1sp1 mpfr_sub1sp1
33 #define MPFR_RoundingMode_mpfr_rnd_t mpfr_rnd_t
34 #define MPFR_Lib_mpfr_struct __mpfr_struct
35 #define MPFR_Lib_gmp_NUMB_BITS GMP_NUMB_BITS
36 #define __eq__MPFR_RoundingMode_mpfr_rnd_t(x,y) ((x)==(y))
37 #define MPFR_RoundingMode_MPFR_RNDD MPFR_RNDD
38 #define MPFR_RoundingMode_MPFR_RNDN MPFR_RNDN
39 #define MPFR_RoundingMode_MPFR_RNDZ MPFR_RNDZ
40 #define MPFR_RoundingMode_MPFR_RNDU MPFR_RNDU
41 #define MPFR_Lib_mpfr_SET_EXP MPFR_SET_EXP
42 #define MPFR_Lib_mpfr_RET MPFR_RET
43 #define MPFR_Lib_mpfr_NEG_SIGN(x) (-(x))
44 #define MPFR_Exceptions_mpfr_underflow mpfr_underflow
45 #define MPFR_Exceptions_mpfr_overflow  mpfr_overflow
46 #define true 1
47 #define false 0
48 
49 /* the original code had mpfr_exp instead of _mpfr_exp */
50 #define mpfr_exp _mpfr_exp
51 /* the original code had mpfr_d instead of _mpfr_d */
52 #define mpfr_d _mpfr_d
53 /* the original code had mpfr_prec instead of _mpfr_prec */
54 #define mpfr_prec _mpfr_prec
55 /* the original code had mpfr_sign instead of _mpfr_sign */
56 #define mpfr_sign _mpfr_sign
57 #define bool int /* to avoid conflict with C++ keyword */
58 
59 /* end of manually added declarations */
60 
MPFR_Lib_Clz_count_leading_zeros(uint64_t a)61 static uint32_t MPFR_Lib_Clz_count_leading_zeros (uint64_t a) {
62   return __builtin_clzll(a);
63 }
64 
65 typedef struct MPFR_Add1sp1_state_s
66 {
67   int64_t sh;
68   int64_t bx;
69   uint64_t rb;
70   uint64_t sb;
71 }
72 MPFR_Add1sp1_state;
73 
74 typedef struct
75 K___MPFR_Lib_mpfr_struct__MPFR_Lib_mpfr_struct__int64_t_int64_t_uint64_t__uint64_t__s
76 {
77   const MPFR_Lib_mpfr_struct *fst; /* added const */
78   const MPFR_Lib_mpfr_struct *snd; /* added const */
79   int64_t thd;
80   int64_t f3;
81   uint64_t *f4;
82   uint64_t *f5;
83 }
84 K___MPFR_Lib_mpfr_struct__MPFR_Lib_mpfr_struct__int64_t_int64_t_uint64_t__uint64_t_;
85 
86 static MPFR_Add1sp1_state
MPFR_Add1sp1_mk_state(int64_t sh,int64_t bx,uint64_t rb,uint64_t sb)87 MPFR_Add1sp1_mk_state(int64_t sh, int64_t bx, uint64_t rb, uint64_t sb)
88 {
89   MPFR_Add1sp1_state lit;
90   lit.sh = sh;
91   lit.bx = bx;
92   lit.rb = rb;
93   lit.sb = sb;
94   return lit;
95 }
96 
97 static MPFR_Add1sp1_state
MPFR_Sub1sp1_mpfr_sub1sp1_gt_branch_1(MPFR_Lib_mpfr_struct * a,const MPFR_Lib_mpfr_struct * b,const MPFR_Lib_mpfr_struct * c,uint64_t * ap,uint64_t * bp,uint64_t * cp,int64_t bx,int64_t cx,int64_t p,int64_t sh,uint64_t mask,uint64_t sb_1,uint64_t a0_base)98 MPFR_Sub1sp1_mpfr_sub1sp1_gt_branch_1(
99   MPFR_Lib_mpfr_struct *a,
100   const MPFR_Lib_mpfr_struct *b, /* added const */
101   const MPFR_Lib_mpfr_struct *c, /* added const */
102   uint64_t *ap,
103   uint64_t *bp,
104   uint64_t *cp,
105   int64_t bx,
106   int64_t cx,
107   int64_t p,
108   int64_t sh,
109   uint64_t mask,
110   uint64_t sb_1,
111   uint64_t a0_base
112 )
113 {
114   uint32_t cnt = MPFR_Lib_Clz_count_leading_zeros(a0_base);
115   uint64_t a0;
116   if (cnt == (uint32_t)0U)
117   {
118     a0 = a0_base;
119   }
120   else
121   {
122     a0 = a0_base << cnt | sb_1 >> ((uint32_t)64U - cnt);
123   }
124   {
125     uint64_t sb_2 = sb_1 << cnt;
126     uint64_t rb = a0 & (uint64_t)1U << (uint32_t)(sh - (int64_t)1);
127     uint64_t sb = sb_2 | ((a0 & mask) ^ rb);
128     ap[0U] = a0 & ~mask;
129     return MPFR_Add1sp1_mk_state(sh, bx - (int64_t)cnt, rb, sb);
130   }
131 }
132 
MPFR_RoundingMode_uu___is_MPFR_RNDN(MPFR_RoundingMode_mpfr_rnd_t projectee)133 static bool MPFR_RoundingMode_uu___is_MPFR_RNDN(MPFR_RoundingMode_mpfr_rnd_t projectee)
134 {
135   switch (projectee)
136   {
137     case MPFR_RoundingMode_MPFR_RNDN:
138       {
139         return true;
140       }
141     default:
142       {
143         return false;
144       }
145   }
146 }
147 
MPFR_RoundingMode_uu___is_MPFR_RNDZ(MPFR_RoundingMode_mpfr_rnd_t projectee)148 static bool MPFR_RoundingMode_uu___is_MPFR_RNDZ(MPFR_RoundingMode_mpfr_rnd_t projectee)
149 {
150   switch (projectee)
151   {
152     case MPFR_RoundingMode_MPFR_RNDZ:
153       {
154         return true;
155       }
156     default:
157       {
158         return false;
159       }
160   }
161 }
162 
MPFR_RoundingMode_uu___is_MPFR_RNDU(MPFR_RoundingMode_mpfr_rnd_t projectee)163 static bool MPFR_RoundingMode_uu___is_MPFR_RNDU(MPFR_RoundingMode_mpfr_rnd_t projectee)
164 {
165   switch (projectee)
166   {
167     case MPFR_RoundingMode_MPFR_RNDU:
168       {
169         return true;
170       }
171     default:
172       {
173         return false;
174       }
175   }
176 }
177 
MPFR_RoundingMode_uu___is_MPFR_RNDD(MPFR_RoundingMode_mpfr_rnd_t projectee)178 static bool MPFR_RoundingMode_uu___is_MPFR_RNDD(MPFR_RoundingMode_mpfr_rnd_t projectee)
179 {
180   switch (projectee)
181   {
182     case MPFR_RoundingMode_MPFR_RNDD:
183       {
184         return true;
185       }
186     default:
187       {
188         return false;
189       }
190   }
191 }
192 
193 static int32_t
MPFR_Sub1sp1_mpfr_sub1sp1(MPFR_Lib_mpfr_struct * a,const MPFR_Lib_mpfr_struct * b,const MPFR_Lib_mpfr_struct * c,MPFR_RoundingMode_mpfr_rnd_t rnd_mode,int64_t p)194 MPFR_Sub1sp1_mpfr_sub1sp1(
195   MPFR_Lib_mpfr_struct *a,
196   const MPFR_Lib_mpfr_struct *b, /* added const */
197   const MPFR_Lib_mpfr_struct *c, /* added const */
198   MPFR_RoundingMode_mpfr_rnd_t rnd_mode,
199   int64_t p
200 )
201 {
202   int64_t bx = b->mpfr_exp;
203   int64_t cx = c->mpfr_exp;
204   uint64_t *ap = a->mpfr_d;
205   uint64_t *bp = b->mpfr_d;
206   uint64_t *cp = c->mpfr_d;
207   int64_t sh = MPFR_Lib_gmp_NUMB_BITS - p;
208   uint64_t bp0ul = bp[0U];
209   uint64_t cp0ul = cp[0U];
210   if (bx == cx && bp0ul == cp0ul)
211   {
212     if (__eq__MPFR_RoundingMode_mpfr_rnd_t(rnd_mode, MPFR_RoundingMode_MPFR_RNDD))
213     {
214       MPFR_Lib_mpfr_struct uu____0 = a[0U];
215       MPFR_Lib_mpfr_struct lit;
216       lit.mpfr_prec = uu____0.mpfr_prec;
217       lit.mpfr_sign = (int32_t)-1;
218       lit.mpfr_exp = uu____0.mpfr_exp;
219       lit.mpfr_d = uu____0.mpfr_d;
220       a[0U] = lit;
221     }
222     else
223     {
224       MPFR_Lib_mpfr_struct uu____1 = a[0U];
225       MPFR_Lib_mpfr_struct lit;
226       lit.mpfr_prec = uu____1.mpfr_prec;
227       lit.mpfr_sign = (int32_t)1;
228       lit.mpfr_exp = uu____1.mpfr_exp;
229       lit.mpfr_d = uu____1.mpfr_d;
230       a[0U] = lit;
231     }
232     MPFR_Lib_mpfr_SET_EXP(a, (int64_t)-0x7fffffffffffffff);
233     /* the following return was commented out from the extracted code */
234     /*return*/ MPFR_Lib_mpfr_RET((int32_t)0);
235   }
236   else
237   {
238     MPFR_Add1sp1_state st;
239     if (bx == cx)
240     {
241       /* Prims_int vb = FStar_UInt64_v(bp[0U]); */ /* unused */
242       /* Prims_int vc = FStar_UInt64_v(cp[0U]); */ /* unused */
243       /* Prims_int vsh = FStar_Int64_v(sh); */     /* unused */
244       if (cp[0U] > bp[0U])
245       {
246         uint64_t a0 = cp[0U] - bp[0U];
247         uint32_t cnt = MPFR_Lib_Clz_count_leading_zeros(a0);
248         int32_t uu____2 = MPFR_Lib_mpfr_NEG_SIGN(b->mpfr_sign);
249         MPFR_Lib_mpfr_struct uu____3 = a[0U];
250         MPFR_Lib_mpfr_struct lit;
251         lit.mpfr_prec = uu____3.mpfr_prec;
252         lit.mpfr_sign = uu____2;
253         lit.mpfr_exp = uu____3.mpfr_exp;
254         lit.mpfr_d = uu____3.mpfr_d;
255         a[0U] = lit;
256         ap[0U] = a0 << cnt;
257         {
258           int64_t bx1 = bx - (int64_t)cnt;
259           st = MPFR_Add1sp1_mk_state(sh, bx1, (uint64_t)0U, (uint64_t)0U);
260         }
261       }
262       else
263       {
264         uint64_t a0 = bp[0U] - cp[0U];
265         uint32_t cnt = MPFR_Lib_Clz_count_leading_zeros(a0);
266         MPFR_Lib_mpfr_struct uu____4 = a[0U];
267         MPFR_Lib_mpfr_struct lit;
268         lit.mpfr_prec = uu____4.mpfr_prec;
269         lit.mpfr_sign = b->mpfr_sign;
270         lit.mpfr_exp = uu____4.mpfr_exp;
271         lit.mpfr_d = uu____4.mpfr_d;
272         a[0U] = lit;
273         ap[0U] = a0 << cnt;
274         {
275           int64_t bx1 = bx - (int64_t)cnt;
276           st = MPFR_Add1sp1_mk_state(sh, bx1, (uint64_t)0U, (uint64_t)0U);
277         }
278       }
279     }
280     else
281     {
282       K___MPFR_Lib_mpfr_struct__MPFR_Lib_mpfr_struct__int64_t_int64_t_uint64_t__uint64_t_ scrut;
283       if (bx >= cx)
284       {
285         MPFR_Lib_mpfr_struct uu____5 = a[0U];
286         MPFR_Lib_mpfr_struct lit;
287         lit.mpfr_prec = uu____5.mpfr_prec;
288         lit.mpfr_sign = b->mpfr_sign;
289         lit.mpfr_exp = uu____5.mpfr_exp;
290         lit.mpfr_d = uu____5.mpfr_d;
291         a[0U] = lit;
292         {
293           K___MPFR_Lib_mpfr_struct__MPFR_Lib_mpfr_struct__int64_t_int64_t_uint64_t__uint64_t_ lit0;
294           lit0.fst = b;
295           lit0.snd = c;
296           lit0.thd = bx;
297           lit0.f3 = cx;
298           lit0.f4 = bp;
299           lit0.f5 = cp;
300           scrut = lit0;
301         }
302       }
303       else
304       {
305         int32_t uu____6 = MPFR_Lib_mpfr_NEG_SIGN(b->mpfr_sign);
306         MPFR_Lib_mpfr_struct uu____7 = a[0U];
307         MPFR_Lib_mpfr_struct lit;
308         lit.mpfr_prec = uu____7.mpfr_prec;
309         lit.mpfr_sign = uu____6;
310         lit.mpfr_exp = uu____7.mpfr_exp;
311         lit.mpfr_d = uu____7.mpfr_d;
312         a[0U] = lit;
313         {
314           K___MPFR_Lib_mpfr_struct__MPFR_Lib_mpfr_struct__int64_t_int64_t_uint64_t__uint64_t_ lit0;
315           lit0.fst = c;
316           lit0.snd = b;
317           lit0.thd = cx;
318           lit0.f3 = bx;
319           lit0.f4 = cp;
320           lit0.f5 = bp;
321           scrut = lit0;
322         }
323       }
324       {
325         const MPFR_Lib_mpfr_struct *b1 = scrut.fst; /* added const */
326         const MPFR_Lib_mpfr_struct *c1 = scrut.snd; /* added const */
327         int64_t bx1 = scrut.thd;
328         int64_t cx1 = scrut.f3;
329         uint64_t *bp1 = scrut.f4;
330         uint64_t *cp1 = scrut.f5;
331         int64_t d = bx1 - cx1;
332         uint64_t bp0ul1 = bp1[0U];
333         uint64_t cp0ul1 = cp1[0U];
334         uint64_t mask = ((uint64_t)1U << (uint32_t)sh) - (uint64_t)1U;
335         if (d < (int64_t)64)
336         {
337           uint64_t sb_1 = ~(cp0ul1 << (uint32_t)(MPFR_Lib_gmp_NUMB_BITS - d)) + (uint64_t)1U;
338           uint64_t ite;
339           if (sb_1 == (uint64_t)0U)
340           {
341             ite = (uint64_t)0U;
342           }
343           else
344           {
345             ite = (uint64_t)1U;
346           }
347           st =
348             MPFR_Sub1sp1_mpfr_sub1sp1_gt_branch_1(a,
349               b1,
350               c1,
351               ap,
352               bp1,
353               cp1,
354               bx1,
355               cx1,
356               p,
357               sh,
358               mask,
359               sb_1,
360               bp0ul1 - ite - (cp0ul1 >> (uint32_t)d));
361         }
362         else if (bp0ul1 > (uint64_t)0x8000000000000000U)
363         {
364           ap[0U] = bp0ul1 - ((uint64_t)1U << (uint32_t)sh);
365           st = MPFR_Add1sp1_mk_state(sh, bx1, (uint64_t)1U, (uint64_t)1U);
366         }
367         else
368         {
369           bool
370           rb =
371             sh
372             > (int64_t)1
373             || d > MPFR_Lib_gmp_NUMB_BITS
374             || cp0ul1 == (uint64_t)0x8000000000000000U;
375           bool
376           sb =
377             sh
378             > (int64_t)1
379             || d > MPFR_Lib_gmp_NUMB_BITS
380             || cp0ul1 != (uint64_t)0x8000000000000000U;
381           ap[0U] = ~mask;
382           {
383             uint64_t ite0;
384             if (rb)
385             {
386               ite0 = (uint64_t)1U;
387             }
388             else
389             {
390               ite0 = (uint64_t)0U;
391             }
392             {
393               uint64_t ite;
394               if (sb)
395               {
396                 ite = (uint64_t)1U;
397               }
398               else
399               {
400                 ite = (uint64_t)0U;
401               }
402               st = MPFR_Add1sp1_mk_state(sh, bx1 - (int64_t)1, ite0, ite);
403             }
404           }
405         }
406       }
407     }
408     /* the constant (int64_t)-0x000000003fffffff from the original extracted
409        code was manually replaced by __gmpfr_emin */
410     if (st.bx < __gmpfr_emin)
411     {
412       int32_t s = a->mpfr_sign;
413       uint64_t ap0ul = ap[0U];
414       if
415       (
416         __eq__MPFR_RoundingMode_mpfr_rnd_t(rnd_mode,
417           MPFR_RoundingMode_MPFR_RNDN)
418         /* the constant (int64_t)-1073741824 from the original extracted
419            code was manually replaced by __gmpfr_emin-1 */
420         && (st.bx < __gmpfr_emin - 1 || ap0ul == (uint64_t)0x8000000000000000U)
421       )
422       {
423         MPFR_Lib_mpfr_SET_EXP(a, (int64_t)-0x7fffffffffffffff);
424         return MPFR_Lib_mpfr_NEG_SIGN(s);
425       }
426       else
427       {
428         int32_t t = MPFR_Exceptions_mpfr_underflow(a, rnd_mode, s);
429         return t;
430       }
431     }
432     else
433     {
434       uint64_t a0 = ap[0U];
435       MPFR_Lib_mpfr_SET_EXP(a, st.bx);
436       if (st.rb == (uint64_t)0U && st.sb == (uint64_t)0U)
437       {
438         /* the following return was commented out from the extracted code */
439         /*return*/ MPFR_Lib_mpfr_RET((int32_t)0);
440       }
441       else if (MPFR_RoundingMode_uu___is_MPFR_RNDN(rnd_mode))
442       {
443         if
444         (
445           st.rb
446           == (uint64_t)0U
447           || (st.sb == (uint64_t)0U && (a0 & (uint64_t)1U << (uint32_t)st.sh) == (uint64_t)0U)
448         )
449         {
450           /* the following return was commented out from the extracted code */
451           /*return*/ MPFR_Lib_mpfr_RET(MPFR_Lib_mpfr_NEG_SIGN(a->mpfr_sign));
452         }
453         else if (ap[0U] + ((uint64_t)1U << (uint32_t)st.sh) == (uint64_t)0U)
454         {
455           ap[0U] = ap[0U] + ((uint64_t)1U << (uint32_t)st.sh);
456           ap[0U] = (uint64_t)0x8000000000000000U;
457           /* the constant (int64_t)0x000000003fffffff from the original
458              extracted code was replaced by __gmpfr_emax */
459           if (st.bx + (int64_t)1 <= __gmpfr_emax)
460           {
461             MPFR_Lib_mpfr_SET_EXP(a, st.bx + (int64_t)1);
462             /* the following return was commented out from the extracted code */
463             /*return*/ MPFR_Lib_mpfr_RET(a->mpfr_sign);
464           }
465           else
466           {
467             int32_t t = MPFR_Exceptions_mpfr_overflow(a, rnd_mode, a->mpfr_sign);
468             /* the following return was commented out from the extracted code */
469             /*return*/ MPFR_Lib_mpfr_RET(t);
470           }
471         }
472         else
473         {
474           ap[0U] = ap[0U] + ((uint64_t)1U << (uint32_t)st.sh);
475           /* the following return was commented out from the extracted code */
476           /*return*/ MPFR_Lib_mpfr_RET(a->mpfr_sign);
477         }
478       }
479       else
480       {
481         bool uu____8 = a->mpfr_sign < (int32_t)0;
482         if
483         (
484           MPFR_RoundingMode_uu___is_MPFR_RNDZ(rnd_mode)
485           || (MPFR_RoundingMode_uu___is_MPFR_RNDU(rnd_mode) && uu____8)
486           || (MPFR_RoundingMode_uu___is_MPFR_RNDD(rnd_mode) && !uu____8)
487         )
488         {
489           /* the following return was commented out from the extracted code */
490           /*return*/ MPFR_Lib_mpfr_RET(MPFR_Lib_mpfr_NEG_SIGN(a->mpfr_sign));
491         }
492         else if (ap[0U] + ((uint64_t)1U << (uint32_t)st.sh) == (uint64_t)0U)
493         {
494           ap[0U] = ap[0U] + ((uint64_t)1U << (uint32_t)st.sh);
495           ap[0U] = (uint64_t)0x8000000000000000U;
496           /* the constant (int64_t)0x000000003fffffff from the original
497              extracted code was replaced by __gmpfr_emax */
498           if (st.bx + (int64_t)1 <= __gmpfr_emax)
499           {
500             MPFR_Lib_mpfr_SET_EXP(a, st.bx + (int64_t)1);
501             /* the following return was commented out from the extracted code */
502             /*return*/ MPFR_Lib_mpfr_RET(a->mpfr_sign);
503           }
504           else
505           {
506             int32_t t = MPFR_Exceptions_mpfr_overflow(a, rnd_mode, a->mpfr_sign);
507             /* the following return was commented out from the extracted code */
508             /*return*/ MPFR_Lib_mpfr_RET(t);
509           }
510         }
511         else
512         {
513           ap[0U] = ap[0U] + ((uint64_t)1U << (uint32_t)st.sh);
514           /* the following return was commented out from the extracted code */
515           /*return*/ MPFR_Lib_mpfr_RET(a->mpfr_sign);
516         }
517       }
518     }
519   }
520 }
521 
522 int32_t
523 (*MPFR_mpfr_sub1sp1)(
524   MPFR_Lib_mpfr_struct *x0,
525   const MPFR_Lib_mpfr_struct *x1, /* added const */
526   const MPFR_Lib_mpfr_struct *x2, /* added const */
527   MPFR_RoundingMode_mpfr_rnd_t x3,
528   int64_t x4
529 ) = MPFR_Sub1sp1_mpfr_sub1sp1;
530 
531