Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:15:27

0001 /*
0002     Copyright (C) 2023 Albin Ahlbäck
0003 
0004     This file is part of FLINT.
0005 
0006     FLINT is free software: you can redistribute it and/or modify it under
0007     the terms of the GNU Lesser General Public License (LGPL) as published
0008     by the Free Software Foundation; either version 3 of the License, or
0009     (at your option) any later version.  See <https://www.gnu.org/licenses/>.
0010 */
0011 
0012 #ifndef LONGLONG_MSC_H
0013 #define LONGLONG_MSC_H
0014 
0015 #include <stdlib.h>
0016 #include <intrin.h>
0017 #include <immintrin.h>
0018 
0019 #if defined(_M_IX86) || FLINT_BITS == 32
0020 
0021 /* Trailing and leading zeros */
0022 # define flint_clz _lzcnt_u32
0023 # define flint_ctz _tzcnt_u32
0024 
0025 /* Addition and subtraction */
0026 # define _FLINT_ADC _addcarry_u32
0027 # define _FLINT_SBB _subborrow_u32
0028 
0029 /* Multiplication */
0030 # define umul_ppmm(r1, r0, u, v) \
0031 do \
0032 { \
0033     unsigned __int64 _tmp = __emulu(u, v); \
0034     (r0) = _tmp; \
0035     (r1) = _tmp >> 32; \
0036 } while (0)
0037 
0038 # define smul_ppmm(r1, r0, u, v) \
0039 do \
0040 { \
0041     __int64 _tmp = __emul(u, v); \
0042     (r0) = _tmp; \
0043     (r1) = _tmp >> 32; \
0044 } while (0)
0045 
0046 /* Division */
0047 # define _FLINT_DIV(_n1, _n0, _dx, _rp) _udiv64((unsigned __int64) (_n1) | (unsigned __int64) (_n0), _dx, _rp)
0048 # define _FLINT_IDIV(_n1, _n0, _dx, _rp) _div64((__int64) (_n1) | (__int64) (_n0), _dx, _rp)
0049 
0050 #else
0051 
0052 /* Trailing and leading zeros */
0053 # define flint_clz _lzcnt_u64
0054 # define flint_ctz _tzcnt_u64
0055 
0056 /* Addition and subtraction */
0057 # define _FLINT_ADC _addcarry_u64
0058 # define _FLINT_SBB _subborrow_u64
0059 
0060 /* Multiplication */
0061 #define umul_ppmm(r1, r0, u, v) do { (r0) = _umul128(u, v, (unsigned __int64 *) &(r1)); } while (0)
0062 #define smul_ppmm(r1, r0, u, v) do { (r0) = _mul128(u, v, (__int64 *) &(r1)); } while (0)
0063 
0064 /* Division */
0065 # define _FLINT_DIV _udiv128
0066 # define _FLINT_IDIV _div128
0067 
0068 #endif
0069 
0070 /* Addition and subtraction */
0071 #define add_ssaaaa(s1, s0, a1, a0, b1, b0) \
0072 do \
0073 { \
0074     unsigned char _carry; \
0075     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0076     _FLINT_ADC(_carry, a1, b1, &(s1)); \
0077 } while (0)
0078 
0079 #define add_sssaaaaaa(s2, s1, s0, a2, a1, a0, b2, b1, b0) \
0080 do \
0081 { \
0082     unsigned char _carry; \
0083     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0084     _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
0085     _FLINT_ADC(_carry, a2, b2, &(s2)); \
0086 } while (0)
0087 
0088 #define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \
0089 do \
0090 { \
0091     unsigned char _carry; \
0092     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0093     _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
0094     _carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
0095     _FLINT_ADC(_carry, a3, b3, &(s3)); \
0096 } while (0)
0097 
0098 #define add_sssssaaaaaaaaaa(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \
0099 do \
0100 { \
0101     unsigned char _carry; \
0102     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0103     _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
0104     _carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
0105     _carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
0106     _FLINT_ADC(_carry, a4, b4, &(s4)); \
0107 } while (0)
0108 
0109 #define add_ssssssaaaaaaaaaaaa(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \
0110 do \
0111 { \
0112     unsigned char _carry; \
0113     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0114     _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
0115     _carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
0116     _carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
0117     _carry = _FLINT_ADC(_carry, a4, b4, &(s4)); \
0118     _FLINT_ADC(_carry, a5, b5, &(s5)); \
0119 } while (0)
0120 
0121 #define add_sssssssaaaaaaaaaaaaaa(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \
0122 do \
0123 { \
0124     unsigned char _carry; \
0125     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0126     _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
0127     _carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
0128     _carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
0129     _carry = _FLINT_ADC(_carry, a4, b4, &(s4)); \
0130     _carry = _FLINT_ADC(_carry, a5, b5, &(s5)); \
0131     _FLINT_ADC(_carry, a6, b6, &(s6)); \
0132 } while (0)
0133 
0134 #define add_ssssssssaaaaaaaaaaaaaaaa(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \
0135 do \
0136 { \
0137     unsigned char _carry; \
0138     _carry = _FLINT_ADC(0, a0, b0, &(s0)); \
0139     _carry = _FLINT_ADC(_carry, a1, b1, &(s1)); \
0140     _carry = _FLINT_ADC(_carry, a2, b2, &(s2)); \
0141     _carry = _FLINT_ADC(_carry, a3, b3, &(s3)); \
0142     _carry = _FLINT_ADC(_carry, a4, b4, &(s4)); \
0143     _carry = _FLINT_ADC(_carry, a5, b5, &(s5)); \
0144     _carry = _FLINT_ADC(_carry, a6, b6, &(s6)); \
0145     _FLINT_ADC(_carry, a7, b7, &(s7)); \
0146 } while (0)
0147 
0148 
0149 #define sub_ddmmss(s1, s0, a1, a0, b1, b0) \
0150 do \
0151 { \
0152     unsigned char _carry; \
0153     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0154     _FLINT_SBB(_carry, a1, b1, &(s1)); \
0155 } while (0)
0156 
0157 #define sub_dddmmmsss(s2, s1, s0, a2, a1, a0, b2, b1, b0) \
0158 do \
0159 { \
0160     unsigned char _carry; \
0161     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0162     _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
0163     _FLINT_SBB(_carry, a2, b2, &(s2)); \
0164 } while (0)
0165 
0166 #define sub_ddddmmmmssss(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \
0167 do \
0168 { \
0169     unsigned char _carry; \
0170     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0171     _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
0172     _carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
0173     _FLINT_SBB(_carry, a3, b3, &(s3)); \
0174 } while (0)
0175 
0176 #define sub_dddddmmmmmsssss(s4, s3, s2, s1, s0, a4, a3, a2, a1, a0, b4, b3, b2, b1, b0) \
0177 do \
0178 { \
0179     unsigned char _carry; \
0180     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0181     _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
0182     _carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
0183     _carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
0184     _FLINT_SBB(_carry, a4, b4, &(s4)); \
0185 } while (0)
0186 
0187 #define sub_ddddddmmmmmmssssss(s5, s4, s3, s2, s1, s0, a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0) \
0188 do \
0189 { \
0190     unsigned char _carry; \
0191     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0192     _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
0193     _carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
0194     _carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
0195     _carry = _FLINT_SBB(_carry, a4, b4, &(s4)); \
0196     _FLINT_SBB(_carry, a5, b5, &(s5)); \
0197 } while (0)
0198 
0199 #define sub_dddddddmmmmmmmsssssss(s6, s5, s4, s3, s2, s1, s0, a6, a5, a4, a3, a2, a1, a0, b6, b5, b4, b3, b2, b1, b0) \
0200 do \
0201 { \
0202     unsigned char _carry; \
0203     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0204     _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
0205     _carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
0206     _carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
0207     _carry = _FLINT_SBB(_carry, a4, b4, &(s4)); \
0208     _carry = _FLINT_SBB(_carry, a5, b5, &(s5)); \
0209     _FLINT_SBB(_carry, a6, b6, &(s6)); \
0210 } while (0)
0211 
0212 
0213 #define sub_ddddddddmmmmmmmmssssssss(s7, s6, s5, s4, s3, s2, s1, s0, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) \
0214 do \
0215 { \
0216     unsigned char _carry; \
0217     _carry = _FLINT_SBB(0, a0, b0, &(s0)); \
0218     _carry = _FLINT_SBB(_carry, a1, b1, &(s1)); \
0219     _carry = _FLINT_SBB(_carry, a2, b2, &(s2)); \
0220     _carry = _FLINT_SBB(_carry, a3, b3, &(s3)); \
0221     _carry = _FLINT_SBB(_carry, a4, b4, &(s4)); \
0222     _carry = _FLINT_SBB(_carry, a5, b5, &(s5)); \
0223     _carry = _FLINT_SBB(_carry, a6, b6, &(s6)); \
0224     _FLINT_SBB(_carry, a7, b7, &(s7)); \
0225 } while (0)
0226 
0227 /* Division */
0228 #define udiv_qrnnd(q, r, n1, n0, dx) do { (q) = _FLINT_DIV(n1, n0, dx, &(r)); } while (0)
0229 #define sdiv_qrnnd(q, r, n1, n0, dx) do { (q) = _FLINT_IDIV(n1, n0, dx, &(r)); } while (0)
0230 
0231 #endif