.file "tgammal.s"


// Copyright (c) 2002 - 2005, Intel Corporation
// All rights reserved.
//
// Contributed 2002 by the Intel Numerics Group, Intel Corporation
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Intel Corporation is the author of this code, and requests that all
// problem reports or change requests be submitted to it directly at
// http://www.intel.com/software/products/opensource/libraries/num.htm.
//
// History
//==============================================================
// 01/16/02  Initial version
// 05/20/02  Cleaned up namespace and sf0 syntax
// 02/10/03  Reordered header: .section, .global, .proc, .align;
//           used data8 for long double table values
// 03/17/03  Moved tgammal_libm_err label into .proc region
// 04/10/03  Changed error codes for overflow and negative integers
// 03/31/05  Reformatted delimiters between data tables
//
// API
//==============================================================
// long double tgammal(long double)
//
// Resources Used:
//
//    Floating-Point Registers:  f8-f15
//                               f32-f127
//
//    General Purpose Registers: r32-r67
//
//    Predicate Registers:       p6-p15
//
//*********************************************************************
//
// IEEE Special Conditions:
//
//    tgammal(+inf) = +inf
//    tgammal(-inf) = QNaN
//    tgammal(+/-0) = +/-inf
//    tgammal(x<0, x - integer) = QNaN
//    tgammal(SNaN) = QNaN
//    tgammal(QNaN) = QNaN
//
//*********************************************************************
// Overview of operation
//==============================================================
//
// Algorithm description
// ---------------------
//
// There are 3 main paths in the implementation
// (and additional special values branches)
//
// 1) |X| >= 13 - Stirling formula computation
//    a) Positive arguments:
//       TGAMMAL(X) = exp((X-0.5)*ln(X) - X + C + S(Z)),
//       where C = 0.5*ln(2*Pi) , Z = 1/Z, S(Z) - Bernulli polynomial
//       (up to 'B18' term).
//       Some of these calculation done in multiprecision.
//       Ln returns multiprecision result too
//       and exp also accepts and returns pair of values.
//
//    b) Negative arguments
//       TGAMMAL(-X) = PI/(X*TGAMMAL(X)*sin(PI*X)).
//       (X*sin(PI*X))/PI calculated in parallel with TGAMMAL.
//       Here we use polynomial of 9th degree with 2 multiprecision steps.
//       Argument range reduction is:
//       N = [x] with round to nearest, r = x - N, -0.5 <= r < 0.5
//       After ((X-0.5)*ln(X) - X + C + S(Z)) completed we just invert
//       its result and compute exp with negative argument (1/exp(x)=exp(-x))
//       Then we multiply exp result to PI/(X*sin(PI*X)).
//
// 2) 1 <= |X| < 13 - Polynomial part
//    a) Positive arguments:
//       All values are splitted to such intervals as:
//       #0->[2;3], #1->[3,4], #2->[5,6]...
//       For even intervals we just use polynomial computation with degree 20
//       and first 6 multiprecision computations.
//       Range reduction looks like
//       N = [x] with truncate, r = x - N - 0.5, -0.5 <= r < 0.5
//       For odd intervals we use reccurent formula:
//       TGAMMAL(X) = TGAMMA(X-1)*(X-1)
//       [1;2] interval is splitted to 3 subranges:
//       [1;1.25], [1.25;1.75], [1.75;2] with the same polynomial forms
//
//    b) Negative arguments
//       TGAMMAL(-X) = PI/(X*TGAMMAL(X)*sin(PI*X)).
//       (X*sin(PI*X))/PI calculated in parallel with TGAMMAL.
//       After multiplication by TGAMMAL(X) result we calculate reciprocal
//       and get final result.
//
// 3) 0 < |X| < 1 - Near 0 part
//    a) Here we use reccurent formula TGAMMAL(X) = TGAMMAL(X+1)/X
//       TGAMMAL(X+1) calculated as shown above,
//       1/X result obtained in parallel. Then we just multiply these values.
//       There is only additional separated subrange: [0;0.125] with specific
//       polynomial constants set.
//
//    b) Negative arguments
//       TGAMMAL(-X) = PI/(TGAMMAL(X+1)*sin(PI*X)).
//       There is no need to compute 1/X.



RODATA

.align 16
LOCAL_OBJECT_START(Constants_Tgammal_log_80_Q)
// log2_hi, log2_lo, Q_6, Q_5, Q_4, Q_3, Q_2, Q_1
data4 0x00000000,0xB1721800,0x00003FFE,0x00000000
data4 0x4361C4C6,0x82E30865,0x0000BFE2,0x00000000
data4 0xA51BE0AF,0x92492453,0x00003FFC,0x00000000
data4 0xA0CFD29F,0xAAAAAB73,0x0000BFFC,0x00000000
data4 0xCCCE3872,0xCCCCCCCC,0x00003FFC,0x00000000
data4 0xFFFFB4FB,0xFFFFFFFF,0x0000BFFC,0x00000000
data4 0xAAAAAAAB,0xAAAAAAAA,0x00003FFD,0x00000000
data4 0x00000000,0x80000000,0x0000BFFE,0x00000000
LOCAL_OBJECT_END(Constants_Tgammal_log_80_Q)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_log_80_Z_G_H_h1)
// Z1 - 16 bit fixed, G1 and H1 IEEE single, h1 IEEE double
data4 0x00008000,0x3F800000,0x00000000,0x00000000
data4 0x00000000,0x00000000,0x00000000,0x00000000
data4 0x00007879,0x3F70F0F0,0x3D785196,0x00000000
data4 0xEBA0E0D1,0x8B1D330B,0x00003FDA,0x00000000
data4 0x000071C8,0x3F638E38,0x3DF13843,0x00000000
data4 0x9EADD553,0xE2AF365E,0x00003FE2,0x00000000
data4 0x00006BCB,0x3F579430,0x3E2FF9A0,0x00000000
data4 0x752F34A2,0xF585FEC3,0x0000BFE3,0x00000000
data4 0x00006667,0x3F4CCCC8,0x3E647FD6,0x00000000
data4 0x893B03F3,0xF3546435,0x00003FE2,0x00000000
data4 0x00006187,0x3F430C30,0x3E8B3AE7,0x00000000
data4 0x39CDD2AC,0xBABA62E0,0x00003FE4,0x00000000
data4 0x00005D18,0x3F3A2E88,0x3EA30C68,0x00000000
data4 0x457978A1,0x8718789F,0x00003FE2,0x00000000
data4 0x0000590C,0x3F321640,0x3EB9CEC8,0x00000000
data4 0x3185E56A,0x9442DF96,0x0000BFE4,0x00000000
data4 0x00005556,0x3F2AAAA8,0x3ECF9927,0x00000000
data4 0x2BBE2CBD,0xCBF9A4BF,0x00003FE4,0x00000000
data4 0x000051EC,0x3F23D708,0x3EE47FC5,0x00000000
data4 0x852D5935,0xF3537535,0x00003FE3,0x00000000
data4 0x00004EC5,0x3F1D89D8,0x3EF8947D,0x00000000
data4 0x46CDF32F,0xA1F1E699,0x0000BFDF,0x00000000
data4 0x00004BDB,0x3F17B420,0x3F05F3A1,0x00000000
data4 0xD8484CE3,0x84A61856,0x00003FE4,0x00000000
data4 0x00004925,0x3F124920,0x3F0F4303,0x00000000
data4 0xFF28821B,0xC7DD97E0,0x0000BFE2,0x00000000
data4 0x0000469F,0x3F0D3DC8,0x3F183EBF,0x00000000
data4 0xEF1FD32F,0xD3C4A887,0x00003FE3,0x00000000
data4 0x00004445,0x3F088888,0x3F20EC80,0x00000000
data4 0x464C76DA,0x84672BE6,0x00003FE5,0x00000000
data4 0x00004211,0x3F042108,0x3F29516A,0x00000000
data4 0x18835FB9,0x9A43A511,0x0000BFE5,0x00000000
LOCAL_OBJECT_END(Constants_Tgammal_log_80_Z_G_H_h1)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_log_80_Z_G_H_h2)
// Z2 - 16 bit fixed, G2 and H2 IEEE single, h2 IEEE double
data4 0x00008000,0x3F800000,0x00000000,0x00000000
data4 0x00000000,0x00000000,0x00000000,0x00000000
data4 0x00007F81,0x3F7F00F8,0x3B7F875D,0x00000000
data4 0x211398BF,0xAD08B116,0x00003FDB,0x00000000
data4 0x00007F02,0x3F7E03F8,0x3BFF015B,0x00000000
data4 0xC376958E,0xB106790F,0x00003FDE,0x00000000
data4 0x00007E85,0x3F7D08E0,0x3C3EE393,0x00000000
data4 0x79A7679A,0xFD03F242,0x0000BFDA,0x00000000
data4 0x00007E08,0x3F7C0FC0,0x3C7E0586,0x00000000
data4 0x05E7AE08,0xF03F81C3,0x0000BFDF,0x00000000
data4 0x00007D8D,0x3F7B1880,0x3C9E75D2,0x00000000
data4 0x049EB22F,0xD1B87D3C,0x00003FDE,0x00000000
data4 0x00007D12,0x3F7A2328,0x3CBDC97A,0x00000000
data4 0x3A9E81E0,0xFABC8B95,0x00003FDF,0x00000000
data4 0x00007C98,0x3F792FB0,0x3CDCFE47,0x00000000
data4 0x7C4B5443,0xF5F3653F,0x00003FDF,0x00000000
data4 0x00007C20,0x3F783E08,0x3CFC15D0,0x00000000
data4 0xF65A1773,0xE78AB204,0x00003FE0,0x00000000
data4 0x00007BA8,0x3F774E38,0x3D0D874D,0x00000000
data4 0x7B8EF695,0xDB7CBFFF,0x0000BFE0,0x00000000
data4 0x00007B31,0x3F766038,0x3D1CF49B,0x00000000
data4 0xCF773FB3,0xC0241AEA,0x0000BFE0,0x00000000
data4 0x00007ABB,0x3F757400,0x3D2C531D,0x00000000
data4 0xC9539FDF,0xFC8F4D48,0x00003FE1,0x00000000
data4 0x00007A45,0x3F748988,0x3D3BA322,0x00000000
data4 0x954665C2,0x9CD035FB,0x0000BFE1,0x00000000
data4 0x000079D1,0x3F73A0D0,0x3D4AE46F,0x00000000
data4 0xDD367A30,0xEC9017C7,0x00003FE1,0x00000000
data4 0x0000795D,0x3F72B9D0,0x3D5A1756,0x00000000
data4 0xCB11189C,0xEE6625D3,0x0000BFE1,0x00000000
data4 0x000078EB,0x3F71D488,0x3D693B9D,0x00000000
data4 0xBE11C424,0xA49C8DB5,0x0000BFE0,0x00000000
LOCAL_OBJECT_END(Constants_Tgammal_log_80_Z_G_H_h2)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_log_80_h3_G_H)
// h3 IEEE double extended, H3 and G3 IEEE single
data4 0x112666B0,0xAAACAAB1,0x00003FD3,0x3F7FFC00
data4 0x9B7FAD21,0x90051030,0x00003FD8,0x3F7FF400
data4 0xF4D783C4,0xA6B46F46,0x00003FDA,0x3F7FEC00
data4 0x11C6DDCA,0xDA148D88,0x0000BFD8,0x3F7FE400
data4 0xCA964D95,0xCE65C1D8,0x0000BFD8,0x3F7FDC00
data4 0x23412D13,0x883838EE,0x0000BFDB,0x3F7FD400
data4 0x983ED687,0xB7E5CFA1,0x00003FDB,0x3F7FCC08
data4 0xE3C3930B,0xDBE23B16,0x0000BFD9,0x3F7FC408
data4 0x48AA4DFC,0x9B92F1FC,0x0000BFDC,0x3F7FBC10
data4 0xCE9C8F7E,0x9A8CEB15,0x0000BFD9,0x3F7FB410
data4 0x0DECE74A,0x8C220879,0x00003FDC,0x3F7FAC18
data4 0x2F053150,0xB25CA912,0x0000BFDA,0x3F7FA420
data4 0xD9A5BE20,0xA5876555,0x00003FDB,0x3F7F9C20
data4 0x2053F087,0xC919BB6E,0x00003FD9,0x3F7F9428
data4 0x041E9A77,0xB70BDA79,0x00003FDC,0x3F7F8C30
data4 0xEA1C9C30,0xF18A5C08,0x00003FDA,0x3F7F8438
data4 0x796D89E5,0xA3790D84,0x0000BFDD,0x3F7F7C40
data4 0xA2915A3A,0xE1852369,0x0000BFDD,0x3F7F7448
data4 0xA39ED868,0xD803858F,0x00003FDC,0x3F7F6C50
data4 0x9417EBB7,0xB2EEE356,0x0000BFDD,0x3F7F6458
data4 0x9BB0D07F,0xED5C1F8A,0x0000BFDC,0x3F7F5C68
data4 0xE87C740A,0xD6D201A0,0x0000BFDD,0x3F7F5470
data4 0x1CA74025,0xE8DEBF5E,0x00003FDC,0x3F7F4C78
data4 0x1F34A7EB,0x9A995A97,0x0000BFDC,0x3F7F4488
data4 0x359EED97,0x9CB0F742,0x0000BFDA,0x3F7F3C90
data4 0xBBC6A1C8,0xD6F833C2,0x0000BFDD,0x3F7F34A0
data4 0xE71090EC,0xE1F68F2A,0x00003FDC,0x3F7F2CA8
data4 0xC160A74F,0xD1881CF1,0x0000BFDB,0x3F7F24B8
data4 0xD78CB5A4,0x9AD05AE2,0x00003FD6,0x3F7F1CC8
data4 0x9A77DC4B,0xE658CB8E,0x0000BFDD,0x3F7F14D8
data4 0x6BD6D312,0xBA281296,0x00003FDC,0x3F7F0CE0
data4 0xF95210D0,0xB478BBEB,0x0000BFDB,0x3F7F04F0
data4 0x38800100,0x39400480,0x39A00640,0x39E00C41 // H's start here
data4 0x3A100A21,0x3A300F22,0x3A4FF51C,0x3A6FFC1D
data4 0x3A87F20B,0x3A97F68B,0x3AA7EB86,0x3AB7E101
data4 0x3AC7E701,0x3AD7DD7B,0x3AE7D474,0x3AF7CBED
data4 0x3B03E1F3,0x3B0BDE2F,0x3B13DAAA,0x3B1BD766
data4 0x3B23CC5C,0x3B2BC997,0x3B33C711,0x3B3BBCC6
data4 0x3B43BAC0,0x3B4BB0F4,0x3B53AF6D,0x3B5BA620
data4 0x3B639D12,0x3B6B9444,0x3B7393BC,0x3B7B8B6D
LOCAL_OBJECT_END(Constants_Tgammal_log_80_h3_G_H)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_stirling)
//0.5*ln(2*Pi)=9.1893853320467266954096885e-01 + 7.2239360881843238220057778e-17
data8 0x3FED67F1C864BEB4, 0x3C94D252F2400510
// Bernulli numbers
data8 0xAAAAAAAAAAAAAAAB, 0x00003FFB //B2 = 8.3333333333333333333333333333e-02
data8 0xBF66C16C16C16C17 //B4 = -2.7777777777777777777777777778e-03
data8 0x3F4A01A01A01A01A //B6 = 7.9365079365079365079365079365e-04
data8 0xBF43813813813814 //B8 = -5.9523809523809523809523809524e-04
data8 0x3F4B951E2B18FF23 //B10 = 8.4175084175084175084175084175e-04
data8 0xBF5F6AB0D9993C7D //B12 = -1.9175269175269175269175269175e-03
data8 0x3F7A41A41A41A41A //B14 = 6.4102564102564102564102564103e-03
data8 0xBF9E4286CB0F5398 //B16 = -2.9550653594771241830065359477e-02
data8 0x3FC6FE96381E0680 //B18 = 1.7964437236883057316493849002e-01
data8 0x3FE0000000000000 // 0.5
LOCAL_OBJECT_END(Constants_Tgammal_stirling)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_sin)
// Polynomial coefficients for the sin(Pi*x)/Pi, 0 <= |x| < 0.5
//A2 = 8.1174242528335360802316245099e-01 + 5.1302254650266899774269946201e-18
data8 0x3FE9F9CB402BC46C, 0x3C57A8B3819B7CEC
//A1 = -1.6449340668482264060656916627e+00 + -3.0210280454695477893051351574e-17
data8 0xBFFA51A6625307D3, 0xBC816A402079D0EF
data8 0xF3AEF1FFCCE6C813, 0x0000BFE3 //A9 = -7.0921197799923779127089910470e-09
data8 0x87D54408E6D4BB9D, 0x00003FE9 //A8 = 2.5300880778252693946712766029e-07
data8 0xEA12033DCE7B8ED9, 0x0000BFED //A7 = -6.9758403885461690048189307819e-06
data8 0x9BA38C952A59D1A8, 0x00003FF2 //A6 = 1.4842878710882320255092707181e-04
data8 0x99C0B55178FF0E38, 0x0000BFF6 //A5 = -2.3460810348048124421268761990e-03
data8 0xD63402E798FEC896, 0x00003FF9 //A4 = 2.6147847817611456327417812320e-02
data8 0xC354723906D95E92, 0x0000BFFC //A3 = -1.9075182412208257558294507774e-01
LOCAL_OBJECT_END(Constants_Tgammal_sin)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_exp_64_Arg)
data4 0x00000000,0xB17217F4,0x00003FF2,0x00000000 // L_hi = hi part log(2)/2^12
data4 0xF278ECE6,0xF473DE6A,0x00003FD4,0x00000000 // L_lo = lo part log(2)/2^12
LOCAL_OBJECT_END(Constants_Tgammal_exp_64_Arg)

LOCAL_OBJECT_START(Constants_Tgammal_exp_64_A)
data4 0xB1B736A0,0xAAAAAAAB,0x00003FFA,0x00000000 // A3
data4 0x90CD6327,0xAAAAAAAB,0x00003FFC,0x00000000 // A2
data4 0xFFFFFFFF,0xFFFFFFFF,0x00003FFD,0x00000000 // A1
LOCAL_OBJECT_END(Constants_Tgammal_exp_64_A)

LOCAL_OBJECT_START(Constants_Tgammal_exp_64_T1)
data4 0x3F800000,0x3F8164D2,0x3F82CD87,0x3F843A29
data4 0x3F85AAC3,0x3F871F62,0x3F88980F,0x3F8A14D5
data4 0x3F8B95C2,0x3F8D1ADF,0x3F8EA43A,0x3F9031DC
data4 0x3F91C3D3,0x3F935A2B,0x3F94F4F0,0x3F96942D
data4 0x3F9837F0,0x3F99E046,0x3F9B8D3A,0x3F9D3EDA
data4 0x3F9EF532,0x3FA0B051,0x3FA27043,0x3FA43516
data4 0x3FA5FED7,0x3FA7CD94,0x3FA9A15B,0x3FAB7A3A
data4 0x3FAD583F,0x3FAF3B79,0x3FB123F6,0x3FB311C4
data4 0x3FB504F3,0x3FB6FD92,0x3FB8FBAF,0x3FBAFF5B
data4 0x3FBD08A4,0x3FBF179A,0x3FC12C4D,0x3FC346CD
data4 0x3FC5672A,0x3FC78D75,0x3FC9B9BE,0x3FCBEC15
data4 0x3FCE248C,0x3FD06334,0x3FD2A81E,0x3FD4F35B
data4 0x3FD744FD,0x3FD99D16,0x3FDBFBB8,0x3FDE60F5
data4 0x3FE0CCDF,0x3FE33F89,0x3FE5B907,0x3FE8396A
data4 0x3FEAC0C7,0x3FED4F30,0x3FEFE4BA,0x3FF28177
data4 0x3FF5257D,0x3FF7D0DF,0x3FFA83B3,0x3FFD3E0C
LOCAL_OBJECT_END(Constants_Tgammal_exp_64_T1)

LOCAL_OBJECT_START(Constants_Tgammal_exp_64_T2)
data4 0x3F800000,0x3F80058C,0x3F800B18,0x3F8010A4
data4 0x3F801630,0x3F801BBD,0x3F80214A,0x3F8026D7
data4 0x3F802C64,0x3F8031F2,0x3F803780,0x3F803D0E
data4 0x3F80429C,0x3F80482B,0x3F804DB9,0x3F805349
data4 0x3F8058D8,0x3F805E67,0x3F8063F7,0x3F806987
data4 0x3F806F17,0x3F8074A8,0x3F807A39,0x3F807FCA
data4 0x3F80855B,0x3F808AEC,0x3F80907E,0x3F809610
data4 0x3F809BA2,0x3F80A135,0x3F80A6C7,0x3F80AC5A
data4 0x3F80B1ED,0x3F80B781,0x3F80BD14,0x3F80C2A8
data4 0x3F80C83C,0x3F80CDD1,0x3F80D365,0x3F80D8FA
data4 0x3F80DE8F,0x3F80E425,0x3F80E9BA,0x3F80EF50
data4 0x3F80F4E6,0x3F80FA7C,0x3F810013,0x3F8105AA
data4 0x3F810B41,0x3F8110D8,0x3F81166F,0x3F811C07
data4 0x3F81219F,0x3F812737,0x3F812CD0,0x3F813269
data4 0x3F813802,0x3F813D9B,0x3F814334,0x3F8148CE
data4 0x3F814E68,0x3F815402,0x3F81599C,0x3F815F37
LOCAL_OBJECT_END(Constants_Tgammal_exp_64_T2)

LOCAL_OBJECT_START(Constants_Tgammal_exp_64_W1)
data8 0x0000000000000000, 0xBE384454171EC4B4
data8 0xBE6947414AA72766, 0xBE5D32B6D42518F8
data8 0x3E68D96D3A319149, 0xBE68F4DA62415F36
data8 0xBE6DDA2FC9C86A3B, 0x3E6B2E50F49228FE
data8 0xBE49C0C21188B886, 0x3E64BFC21A4C2F1F
data8 0xBE6A2FBB2CB98B54, 0x3E5DC5DE9A55D329
data8 0x3E69649039A7AACE, 0x3E54728B5C66DBA5
data8 0xBE62B0DBBA1C7D7D, 0x3E576E0409F1AF5F
data8 0x3E6125001A0DD6A1, 0xBE66A419795FBDEF
data8 0xBE5CDE8CE1BD41FC, 0xBE621376EA54964F
data8 0x3E6370BE476E76EE, 0x3E390D1A3427EB92
data8 0x3E1336DE2BF82BF8, 0xBE5FF1CBD0F7BD9E
data8 0xBE60A3550CEB09DD, 0xBE5CA37E0980F30D
data8 0xBE5C541B4C082D25, 0xBE5BBECA3B467D29
data8 0xBE400D8AB9D946C5, 0xBE5E2A0807ED374A
data8 0xBE66CB28365C8B0A, 0x3E3AAD5BD3403BCA
data8 0x3E526055C7EA21E0, 0xBE442C75E72880D6
data8 0x3E58B2BB85222A43, 0xBE5AAB79522C42BF
data8 0xBE605CB4469DC2BC, 0xBE589FA7A48C40DC
data8 0xBE51C2141AA42614, 0xBE48D087C37293F4
data8 0x3E367A1CA2D673E0, 0xBE51BEBB114F7A38
data8 0xBE6348E5661A4B48, 0xBDF526431D3B9962
data8 0x3E3A3B5E35A78A53, 0xBE46C46C1CECD788
data8 0xBE60B7EC7857D689, 0xBE594D3DD14F1AD7
data8 0xBE4F9C304C9A8F60, 0xBE52187302DFF9D2
data8 0xBE5E4C8855E6D68F, 0xBE62140F667F3DC4
data8 0xBE36961B3BF88747, 0x3E602861C96EC6AA
data8 0xBE3B5151D57FD718, 0x3E561CD0FC4A627B
data8 0xBE3A5217CA913FEA, 0x3E40A3CC9A5D193A
data8 0xBE5AB71310A9C312, 0x3E4FDADBC5F57719
data8 0x3E361428DBDF59D5, 0x3E5DB5DB61B4180D
data8 0xBE42AD5F7408D856, 0x3E2A314831B2B707
LOCAL_OBJECT_END(Constants_Tgammal_exp_64_W1)

LOCAL_OBJECT_START(Constants_Tgammal_exp_64_W2)
data8 0x0000000000000000, 0xBE641F2537A3D7A2
data8 0xBE68DD57AD028C40, 0xBE5C77D8F212B1B6
data8 0x3E57878F1BA5B070, 0xBE55A36A2ECAE6FE
data8 0xBE620608569DFA3B, 0xBE53B50EA6D300A3
data8 0x3E5B5EF2223F8F2C, 0xBE56A0D9D6DE0DF4
data8 0xBE64EEF3EAE28F51, 0xBE5E5AE2367EA80B
data8 0x3E47CB1A5FCBC02D, 0xBE656BA09BDAFEB7
data8 0x3E6E70C6805AFEE7, 0xBE6E0509A3415EBA
data8 0xBE56856B49BFF529, 0x3E66DD3300508651
data8 0x3E51165FC114BC13, 0x3E53333DC453290F
data8 0x3E6A072B05539FDA, 0xBE47CD877C0A7696
data8 0xBE668BF4EB05C6D9, 0xBE67C3E36AE86C93
data8 0xBE533904D0B3E84B, 0x3E63E8D9556B53CE
data8 0x3E212C8963A98DC8, 0xBE33138F032A7A22
data8 0x3E530FA9BC584008, 0xBE6ADF82CCB93C97
data8 0x3E5F91138370EA39, 0x3E5443A4FB6A05D8
data8 0x3E63DACD181FEE7A, 0xBE62B29DF0F67DEC
data8 0x3E65C4833DDE6307, 0x3E5BF030D40A24C1
data8 0x3E658B8F14E437BE, 0xBE631C29ED98B6C7
data8 0x3E6335D204CF7C71, 0x3E529EEDE954A79D
data8 0x3E5D9257F64A2FB8, 0xBE6BED1B854ED06C
data8 0x3E5096F6D71405CB, 0xBE3D4893ACB9FDF5
data8 0xBDFEB15801B68349, 0x3E628D35C6A463B9
data8 0xBE559725ADE45917, 0xBE68C29C042FC476
data8 0xBE67593B01E511FA, 0xBE4A4313398801ED
data8 0x3E699571DA7C3300, 0x3E5349BE08062A9E
data8 0x3E5229C4755BB28E, 0x3E67E42677A1F80D
data8 0xBE52B33F6B69C352, 0xBE6B3550084DA57F
data8 0xBE6DB03FD1D09A20, 0xBE60CBC42161B2C1
data8 0x3E56ED9C78A2B771, 0xBE508E319D0FA795
data8 0xBE59482AFD1A54E9, 0xBE2A17CEB07FD23E
data8 0x3E68BF5C17365712, 0x3E3956F9B3785569
LOCAL_OBJECT_END(Constants_Tgammal_exp_64_W2)



LOCAL_OBJECT_START(Constants_Tgammal_poly)

// Polynomial coefficients for the tgammal(x), 2 <= |x| < 3
//A5 = 2.8360780594841213109180699803e-02 + 2.2504152891014320704380000000e-19
data8 0x3F9D0A9BC49353D2, 0x3C109AEA0F23CE2D
//A4 = 1.0967323400216015538699565468e-01 + 9.9225166000430644587276000000e-18
data8 0x3FBC138B89492C5B, 0x3C66E138506D5652
//A3 = 2.5387124684114281691904579930e-01 + 2.2667777637607113205546600000e-17
data8 0x3FD03F6D2FA4F4F8, 0x3C7A2258DA8CD8B1
data8 0xC5866457328BC39B, 0x00003FE3 //A20 = 5.7487331964156762795056629138e-09
data8 0xE93D9F1ACD59C929, 0x0000BFE4 //A19= -1.3576396100397317396956445658e-08
data8 0xE33389C8F6CBA813, 0x00003FE5 //A18 = 2.6449714924964597501721434271e-08
data8 0x8FE7B25B9CD26D2A, 0x0000BFE7 //A17= -6.7011017946055513660266853311e-08
data8 0xB89F4721BFBC15B0, 0x00003FE8 //A16 = 1.7194280320370423615174419192e-07
data8 0xE49CBDC1874EBABA, 0x0000BFE9 //A15= -4.2582353660153782928729466776e-07
data8 0x913AF50A336129CA, 0x00003FEB //A14 = 1.0820500665257088283172211622e-06
data8 0xABCF0F7313B3B332, 0x0000BFEC //A13= -2.5601510627710417669568115706e-06
//A2 = 6.5455857798133676439533701341e-01 + 1.3292075193155190798867000000e-18
data8 0x3FE4F224D4B7E01C, 0x3C3885014A2B8319
//A1 = 9.3473452162608550164435428087e-01 + 3.2785154201417136611642400000e-17
data8 0x3FEDE9585F1A7093, 0x3C82E63C1B5028BF
//A0 = 1.3293403881791368004172682049e+00 + 2.2005689328949279282607500000e-16
data8 0x3FF544FA6D47B38F, 0x3CAFB6AA9829E81F
data8 0xF3668F799997C76D, 0x00003FED //A12 = 7.2539039479124273660331538367e-06
data8 0xD6C6BBD54CDEAEB1, 0x0000BFEE //A11= -1.2801665282681088568639378920e-05
data8 0x809E4763B06F6883, 0x00003FF1 //A10 = 6.1329973609906572700697893187e-05
data8 0x8443B000F8F9A71A, 0x00003FED //A9 = 3.9417864189995544394564413428e-06
data8 0xC5C7E6D62A6991D8, 0x00003FF4 //A8 = 7.5447412886334708803357581519e-04
data8 0xD2AF690725C62D88, 0x00003FF5 //A7 = 1.6074004848394703022110823298e-03
data8 0xAA44E635D4B7B682, 0x00003FF8 //A6 = 1.0392403425906843901680697839e-02
//
// Polynomial coefficients for the tgammal(x), 4 <= |x| < 5
//A5 = 1.1600674810589555185913468449e+00 + 3.0229979112715124660731000000e-17
data8 0x3FF28FA2EB44D22E, 0x3C816D285234C815
//A4 = 3.1374268565470946334983182169e+00 + 1.3694868953995008497659600000e-16
data8 0x400919734073B1E1, 0x3CA3BC83CD7E9565
//A3 = 7.0834593993741057360580271052e+00 + 3.3899702569039156457249800000e-16
data8 0x401C5576617B6C1F, 0x3CB86D6431213296
data8 0xA4A5FB49C094966B, 0x00003FDA //A20 = 9.3591760106637809309720130828e-12
data8 0xA9260DA0F51D7ED8, 0x00003FDD //A19 = 7.6919898428091669411809372180e-11
data8 0xA16441DFB14BD6E1, 0x00003FE0 //A18 = 5.8713933014370867331213494535e-10
data8 0x95F098D9C2234849, 0x00003FE3 //A17 = 4.3638234584169302324461091035e-09
data8 0x8581817400E5AD2B, 0x00003FE6 //A16 = 3.1084260332429955234755367839e-08
data8 0xE272940E373EBE15, 0x00003FE8 //A15 = 2.1089573544273993580820317236e-07
data8 0xB6B3391145D226FB, 0x00003FEB //A14 = 1.3612217421122787182942706259e-06
data8 0x8B9428C4DF95FCD5, 0x00003FEE //A13 = 8.3195416382628990683949003789e-06
//A2 = 1.2665135075272345943631080445e+01 + 9.8721896915973874255877000000e-16
data8 0x4029548C95A76F38, 0x3CD1C8BE715B8E13
//A1 = 1.6154969393303069580269948347e+01 + 9.6850518810678379641029000000e-16
data8 0x403027AC12FC1E1E, 0x3CD172711C15501B
//A0 = 1.1631728396567448058362970187e+01 + 8.7078125362814179268673000000e-16
data8 0x40274371E7866C65, 0x3CCF5F8A1A5FACA0
data8 0xC94A903114272C03, 0x00003FF0 //A12 = 4.7991576836334427243159066630e-05
data8 0x8844262960E04BE6, 0x00003FF3 //A11 = 2.5990716419283017929486175141e-04
data8 0xAC5418A76767678D, 0x00003FF5 //A10 = 1.3147621245497801180184809726e-03
data8 0xCA231B6EFE959132, 0x00003FF7 //A9 = 6.1687358811367989146517222415e-03
data8 0xDA38E39C13819D2A, 0x00003FF9 //A8 = 2.6638454961912040754759086920e-02
data8 0xD696DF8D8389FE53, 0x00003FFB //A7 = 1.0477995539298934056097943975e-01
data8 0xBDD5C153048BC435, 0x00003FFD //A6 = 3.7077144754791605130056406006e-01
//
// Polynomial coefficients for the tgammal(x), 6 <= |x| < 7
//A5 = 6.7169398121054200601065531373e+01 + 2.9481001527213915901489600000e-15
data8 0x4050CAD76B377BA0, 0x3CEA8DDB2B2DE93E
//A4 = 1.6115104376855398982115730178e+02 + 1.3422421925418824418257300000e-14
data8 0x406424D559BDC687, 0x3D0E397FDB5B33DC
//A3 = 3.1812194028053562533386866562e+02 + 3.9881709875858650942409600000e-14
data8 0x4073E1F377A6CF73, 0x3D26738F63FE9C4C
data8 0xD6E1B5FF90CAABD3, 0x00003FE1 //A20 = 1.5634700199277480081025480635e-09
data8 0xD451987B925DD37E, 0x00003FE4 //A19 = 1.2358576813211397717382327174e-08
data8 0xBFC151B67FA58E6B, 0x00003FE7 //A18 = 8.9292951435632759686382657901e-08
data8 0xA9034C5E1D67572E, 0x00003FEA //A17 = 6.2962205718327848327368724720e-07
data8 0x8E40F6EAA30A71EC, 0x00003FED //A16 = 4.2394926442967995119170095258e-06
data8 0xE3C3541B03A1C350, 0x00003FEF //A15 = 2.7151465666109594512258841637e-05
data8 0xACE2E58436B2DDCE, 0x00003FF2 //A14 = 1.6487723793339152877117376243e-04
data8 0xF7EAF8D8D1CAA3D1, 0x00003FF4 //A13 = 9.4573158112768812533636022369e-04
//A2 = 4.8664351544258869353143381886e+02 + 4.7424047995944376868895400000e-14
data8 0x407E6A4BD6D9463B, 0x3D2AB2868D79E192
//A1 = 5.1615277644992545447166776285e+02 + 3.0901956935588717379242200000e-14
data8 0x40802138E2DC003B, 0x3D216570FB601AEA
//A0 = 2.8788527781504433278314536437e+02 + 2.8213174117085164944959600000e-14
data8 0x4071FE2A1911F7D6, 0x3D1FC3E4CF4DB5AF
data8 0xA72B88E48D3D1BAB, 0x00003FF7 //A12 = 5.1016252919939028020562237471e-03
data8 0xD2EFB1067DB4FFB2, 0x00003FF9 //A11 = 2.5749059441230515023024615917e-02
data8 0xF788AF9522205C24, 0x00003FFB //A10 = 1.2086617635601742290221382521e-01
data8 0x861A6CE06CB29EAF, 0x00003FFE //A9 = 5.2384071807018493367136112163e-01
data8 0x84FBDE0947718B58, 0x00004000 //A8 = 2.0778727617851237754568261869e+00
data8 0xEEC1371E265A2C3A, 0x00004001 //A7 = 7.4610858525146049022238037342e+00
data8 0xBF514B9BE68ED59D, 0x00004003 //A6 = 2.3914694993947572859629197920e+01
//
// Polynomial coefficients for the tgammal(x), 8 <= |x| < 9
//A5 = 5.8487447114416836484451778233e+03 + 4.7365465221455983144182900000e-13
data8 0x40B6D8BEA568B6FD, 0x3D60AA4D44C2589B
//A4 = 1.2796464063087094473303295672e+04 + 1.2373341702514898266244200000e-12
data8 0x40C8FE3B666B532D, 0x3D75C4752C5B4783
//A3 = 2.2837606581322281272150576115e+04 + 2.6598064610627891398831000000e-13
data8 0x40D64D66D23A7764, 0x3D52B77B3A10EA5C
data8 0xB23418F75B0BE22A, 0x00003FE9 //A20 = 3.3192989594206801808678663868e-07
data8 0xA984A7BC8B856ED2, 0x00003FEC //A19 = 2.5260177918662350066375115788e-06
data8 0x921A49729416372C, 0x00003FEF //A18 = 1.7416797068239475136398213598e-05
data8 0xF5BB9415CC399CA4, 0x00003FF1 //A17 = 1.1717449586392814601938207599e-04
data8 0xC50B91A40B81F9DF, 0x00003FF4 //A16 = 7.5166775151159345732094429036e-04
data8 0x96002572326DB203, 0x00003FF7 //A15 = 4.5776541559407384162139204300e-03
data8 0xD81A1A595E4157BA, 0x00003FF9 //A14 = 2.6379634345126284099420760736e-02
data8 0x92B700D0CFECADD8, 0x00003FFC //A13 = 1.4327622675407940907282658100e-01
//A2 = 3.1237895525940199149772524834e+04 + 3.1280450505163186432331700000e-12
data8 0x40DE8179504C0878, 0x3D8B83BB33FBB766
//A1 = 2.9192841741344487672904506326e+04 + 7.9300780509779689630767000000e-13
data8 0x40DC8235DF171691, 0x3D6BE6C780EE54DF
//A0 = 1.4034407293483411194756627083e+04 + 1.4038139346291543309253700000e-12
data8 0x40CB693422315F90, 0x3D78B23746113FCE
data8 0xBAE50807548BC711, 0x00003FFE //A12 = 7.3005724123917935346868107005e-01
data8 0xDE28B1F57E68CFB6, 0x00004000 //A11 = 3.4712338349724065462763671443e+00
data8 0xF4DCA5A5FF901118, 0x00004002 //A10 = 1.5303868912154033908205911714e+01
data8 0xF85AAA1AD5E84E5E, 0x00004004 //A9 = 6.2088539523416399361048051373e+01
data8 0xE5AA8BB1BF02934D, 0x00004006 //A8 = 2.2966619406617480799195651466e+02
data8 0xBF6CFEFD67F59845, 0x00004008 //A7 = 7.6570306334640770654588802417e+02
data8 0x8DB5D2F001635C29, 0x0000400A //A6 = 2.2673639984182571062068713002e+03
//
// Polynomial coefficients for the tgammal(x), 10 <= |x| < 11
//A5 = 7.2546009516580589115619659424e+05 + 1.0343348865365065212891728822e-10
data8 0x412623A830B99290, 0x3DDC6E7C157611C4
//A4 = 1.4756292870840241666883230209e+06 + 8.1516565365333844166705674775e-11
data8 0x4136842D497E56AF, 0x3DD66837E4C3F9EE
//A3 = 2.4356116926500420086085796356e+06 + 3.5508860076560925641351069404e-10
data8 0x4142950DD8A8C1AF, 0x3DF866C8E3DD0980
data8 0xB7FD0D1EEAC38EB4, 0x00003FF1 //A20 = 8.7732544640091602721643775932e-05
data8 0xA9345C64AC750AE9, 0x00003FF4 //A19 = 6.4546407626804942279126469603e-04
data8 0x8BEABC81BE1E93C9, 0x00003FF7 //A18 = 4.2699261134524096128048819443e-03
data8 0xE1CD281EDD7315F8, 0x00003FF9 //A17 = 2.7563646660310313164706189622e-02
data8 0xAD8A5BA6D0FD9758, 0x00003FFC //A16 = 1.6947310643831556048460963841e-01
data8 0xFCDDA464AD3F182E, 0x00003FFE //A15 = 9.8775699098518676937088606052e-01
data8 0xAE0DCE2F7B60D1AE, 0x00004001 //A14 = 5.4391852309591064073782104822e+00
data8 0xE1745D9ABEB8D1A7, 0x00004003 //A13 = 2.8181819161363002758615770457e+01
//A2 = 3.0619656223573554307222366333e+06 + 1.0819940302945474471259520006e-10
data8 0x41475C66CFA967E4, 0x3DDDBDDB2A27334B
//A1 = 2.6099413018962685018777847290e+06 + 3.6851882860056025385268615240e-10
data8 0x4143E98AA6A48974, 0x3DF9530D42589AB6
//A0 = 1.1332783889487853739410638809e+06 + 1.9339350553312096248591829758e-10
data8 0x41314ADE639225C9, 0x3DEA946DD6C2C8D3
data8 0x88BCFAAE71812A1C, 0x00004006 //A12 = 1.3673820009490115307300592012e+02
data8 0x9A770F5AB540A326, 0x00004008 //A11 = 6.1786031215382040427126476507e+02
data8 0xA170C1D2C6B413FC, 0x0000400A //A10 = 2.5830473201524594051391525170e+03
data8 0x9AE56061CB02EB55, 0x0000400C //A9 = 9.9133441230507404119297200255e+03
data8 0x872390769650FBE2, 0x0000400E //A8 = 3.4595564309496661629764193479e+04
data8 0xD3E5E8D6923910C1, 0x0000400F //A7 = 1.0849181904819284819615140521e+05
data8 0x930D70602F50B754, 0x00004011 //A6 = 3.0116351174131169193070583741e+05
//
// Polynomial coefficients for the tgammal(x), 12 <= |x| < 13
//A5 = 1.2249876249976964294910430908e+08 + 6.0051348061679753770848000000e-09
data8 0x419D34BB29FFC39D, 0x3E39CAB72E01818D
//A4 = 2.3482765927605420351028442383e+08 + 1.1874729051592862323641700000e-08
data8 0x41ABFE5F168D56FA, 0x3E4980338AA7B04B
//A3 = 3.6407329688125067949295043945e+08 + 2.6657200942150363994658700000e-08
data8 0x41B5B35150E199A5, 0x3E5C9F79C0EB5300
data8 0xE89AE0F8D726329D, 0x00003FF9 //A20 = 2.8394164465429105626588451540e-02
data8 0xCF90981F86E38013, 0x00003FFC //A19 = 2.0270002071785908652476845915e-01
data8 0xA56C658079CA8C4A, 0x00003FFF //A18 = 1.2923704984019263122675412350e+00
data8 0x80AEF96A67C5615A, 0x00004002 //A17 = 8.0427183300456238315262463506e+00
data8 0xBE886D7529678931, 0x00004004 //A16 = 4.7633230047847868242503413461e+01
data8 0x858EDBA4CE2F7508, 0x00004007 //A15 = 2.6711607799594541057655957154e+02
data8 0xB0B0A3AF388274F0, 0x00004009 //A14 = 1.4135199810126975119809102782e+03
data8 0xDBA87137988751EF, 0x0000400B //A13 = 7.0290552818218513870879313985e+03
//A2 = 4.2828433593031734228134155273e+08 + 3.9760422293645854535247300000e-08
data8 0x41B98719AFEE2947, 0x3E6558A17E0D3007
//A1 = 3.4008253676084774732589721680e+08 + 1.2558352335001093116071000000e-09
data8 0x41B4453F68C2C6EB, 0x3E159338C5BC7EC3
//A0 = 1.3684336546556583046913146973e+08 + 2.6786516700381562934240300000e-08
data8 0x41A05020CAEE5EA5, 0x3E5CC3058A858579
data8 0xFF5E3940FB4BA576, 0x0000400D //A12 = 3.2687111823895439312116108631e+04
data8 0x8A08C124C7F74B6C, 0x00004010 //A11 = 1.4134701786994123329786229006e+05
data8 0x89D701953540BFFB, 0x00004012 //A10 = 5.6459209892773907605385652281e+05
data8 0xFC46344B3116C3AD, 0x00004013 //A9 = 2.0666305367147234406757715163e+06
data8 0xD183EBD7A400151F, 0x00004015 //A8 = 6.8653979211730981618367536737e+06
data8 0x9C083A40742112F4, 0x00004017 //A7 = 2.0451444503543981795037456447e+07
data8 0xCD3C475B1A8B6662, 0x00004018 //A6 = 5.3801245423495149598177886823e+07
LOCAL_OBJECT_END(Constants_Tgammal_poly)


LOCAL_OBJECT_START(Constants_Tgammal_poly_splitted)

// Polynomial coefficients for the tgammal(x), 1 <= |x| < 1.25
//A5 = -9.8199506890310417350775651357e-01+ -3.2546247786122976510752200000e-17
data8 0xBFEF6C80EC38B509, 0xBC82C2FA7A3DE3BD
//A4 = 9.8172808683439960475425323239e-01 + 4.4847611775298520359811400000e-17
data8 0x3FEF6A51055096B0, 0x3C89DA56DE95EFE4
//A3 = -9.0747907608088618225394839101e-01 +-1.0244057366544064435443970000e-16
data8 0xBFED0A118F324B62, 0xBC9D86C7B9EBCFFF
data8 0xB8E3FDAA66CC738E, 0x00003FFB //A20 = 9.0278608095877488976217714815e-02
data8 0xA76067AE1738699C, 0x0000BFFD //A19 =-3.2690738678103132837070881737e-01
data8 0x9D66B13718408C44, 0x00003FFE //A18 = 6.1484820933424283818320582920e-01
data8 0xD4AC67BBB4AE5599, 0x0000BFFE //A17 =-8.3075569470082063491389474937e-01
data8 0xF1426ED1C1488DB3, 0x00003FFE //A16 = 9.4241993542644505594957058785e-01
data8 0xFC12EB07AA6F4B6B, 0x0000BFFE //A15 =-9.8466366707947121954333549690e-01
data8 0xFF2B32CFE5B0DDC8, 0x00003FFE //A14 = 9.9675290656677214804168895915e-01
data8 0xFFD8E7E6FF3662EA, 0x0000BFFE //A13 =-9.9940347089360552383472582319e-01
//A2 = 9.8905599532797250361682017683e-01 + 5.1760162410376024240867300000e-17
data8 0x3FEFA658C23B1578, 0x3C8DD673A61F6FE7
//A1 = -5.7721566490153275452712478000e-01+ -1.0607935612223465065923310000e-16
data8 0xBFE2788CFC6FB618, 0xBC9E9346622D53B7
//A0 = 9.9999999999999988897769753748e-01 + 1.1102230245372554544790880000e-16
data8 0x3FEFFFFFFFFFFFFF, 0x3C9FFFFFFFF51E4E
data8 0xFFF360DF628F0BC9, 0x00003FFE //A12 = 9.9980740979895815468216470840e-01
data8 0xFFEF8F9A72B40480, 0x0000BFFE //A11 = -9.9974916001038145045939523470e-01
data8 0xFFE037B8C7E39952, 0x00003FFE //A10 = 9.9951504002809911822597567307e-01
data8 0xFFC01E08F348BED2, 0x0000BFFE //A9 = -9.9902522772325406705059517941e-01
data8 0xFF83DAC83119B52C, 0x00003FFE //A8 = 9.9810569179053383842734164901e-01
data8 0xFEF9F8AB891ABB24, 0x0000BFFE //A7 = -9.9600176036720260345608796766e-01
data8 0xFE3F0537573C8235, 0x00003FFE //A6 = 9.9314911461918778676646301341e-01
//
// Polynomial coefficients for the tgammal(x), 1.25 <= |x| < 1.75
//A5 = -7.7523052299853054125655660300e-02+ -1.2693512521686721504433600000e-17
data8 0xBFB3D88CFE50601B, 0xBC6D44ED60EE2170
//A4 = 1.4464535904462152982041800442e-01 + 2.5426820829345729856648800000e-17
data8 0x3FC283BD374EB2A9, 0x3C7D50AC436187C3
//A3 = -1.0729480456477220873257039102e-01+ -6.2429894945456418196551000000e-18
data8 0xBFBB77AC1CA2EBA5, 0xBC5CCA6BCC422D41
data8 0xF732D2689F323283, 0x00003FF2 //A20 = 2.3574688251652899567587145422e-04
data8 0xB6B00E23DE89D13A, 0x0000BFF3 //A19 =-3.4844916488842618776630058875e-04
data8 0xE98396FE4A1B2799, 0x00003FF3 //A18 =4.4539265198744452020440735977e-04
data8 0xAF8D235A640DB1A2, 0x0000BFF4 //A17 =-6.6967514303333563295261178346e-04
data8 0x8513B736C918B261, 0x00003FF5 //A16 = 1.0152970456990865810615917715e-03
data8 0xC790A1A2C78D8E17, 0x0000BFF5 //A15 =-1.5225598630329403515321688394e-03
data8 0x959706CFA638CDE2, 0x00003FF6 //A14 = 2.2825614575133879623648932383e-03
data8 0xE050A6021E129860, 0x0000BFF6 //A13 =-3.4227757733947066666295285936e-03
//A2 = 4.1481345368830113695679528973e-01 + 3.1252439808354284892632100000e-17
data8 0x3FDA8C4DBA620D56, 0x3C82040BCB483C76
//A1 = 3.2338397448885010387886751460e-02 + 3.4437825798552300531443100000e-18
data8 0x3FA08EA88EE561B1, 0x3C4FC366D6C64806
//A0 = 8.8622692545275794095971377828e-01 + 7.2689375867553992399219000000e-17
data8 0x3FEC5BF891B4EF6A, 0x3C94F3877D311C0C
data8 0xA8275AADC09D16FC, 0x00003FF7 //A12 = 5.1316445128621071486146117136e-03
data8 0xFBFE2CE9215267A2, 0x0000BFF7 //A11= -7.6902121820788373000579382408e-03
data8 0xBCC8EEAB67ECD91D, 0x00003FF8 //A10 = 1.1522515369164312742737727262e-02
data8 0x8D1614BB97E5E8C2, 0x0000BFF9 //A9 = -1.7222443097804730395560633583e-02
data8 0xD3A963578BE291E3, 0x00003FF9 //A8 = 2.5837606456090186343624210891e-02
data8 0x9BA7EAE64C42FDF7, 0x0000BFFA //A7 = -3.8001935555045161419575037512e-02
data8 0xF0115BA1A77607E7, 0x00003FFA //A6 = 5.8610303817173477119764956736e-02
//
// Polynomial coefficients for the tgammal(x), 1.75 <= |x| < 2.0
//A5 = 2.6698206874501426502654943818e-04 + 3.4033756836921062797887300000e-20
data8 0x3F317F3740FE2A68, 0x3BE417093234B06E
//A4 = 7.4249010753513894345090307070e-02 + 3.9810018444482764697014200000e-18
data8 0x3FB301FBB0F25A92, 0x3C525BEFFABB622F
//A3 = -8.1576919247086265851720554565e-02+ -5.2716624487804746360745000000e-19
data8 0xBFB4E239984650AC, 0xBC2372F1C4F276FF
data8 0xFEF3AEE71038E9A3, 0x00003FEB //A20 = 1.8995395865421509009969188571e-06
data8 0xA11CFA2672BF876A, 0x0000BFEB //A19 =-1.2003868221414015771269244270e-06
data8 0xF8E107215DAE2164, 0x00003FEC //A18 = 3.7085863210303833432006027217e-06
data8 0xBCDDD3FC011EF7D6, 0x00003FEC //A17 = 2.8143303971756051015245433043e-06
data8 0x8683C4687FA22E68, 0x00003FEE //A16 = 8.0177018464360416764308252462e-06
data8 0xFDA09E5D33E32968, 0x00003FEE //A15 = 1.5117372062443781157389064848e-05
data8 0xFFB00D0CFF4089B4, 0x00003FEF //A14 = 3.0480348961227424242198174995e-05
data8 0xFEF6C39566785085, 0x00003FF0 //A13 = 6.0788135974125244644334004947e-05
//A2 = 4.1184033042643969357854416558e-01 + 1.2103396182129232634761000000e-18
data8 0x3FDA5B978B96BEBF, 0x3C3653AAD0A139E4
//A1 = -4.2278433509846713445057275749e-01+ -4.9429151528135657430413000000e-18
data8 0xBFDB0EE6072093CE, 0xBC56CB907027554F
//A0 = 1.0000000000000000000000000000e+00 + 1.0969171200000000000000000000e-31
data8 0x3FF0000000000000, 0x3981CC6A5B20B4D5
data8 0xFF2B7BA9A8D68C37, 0x00003FF1 //A12 = 1.2167446884801403650547161615e-04
data8 0xFCA53468E3692EF1, 0x00003FF2 //A11 = 2.4094136329542400976250900707e-04
data8 0x808D698A9C993615, 0x00003FF4 //A10 = 4.9038845704938303659791698883e-04
data8 0xF10F8E3FB8BB4AFB, 0x00003FF4 //A9 = 9.1957383840999861214472423976e-04
data8 0x89E224E42F93F005, 0x00003FF6 //A8 = 2.1039333407187324139473634747e-03
data8 0xBAF374824937A323, 0x00003FF6 //A7 = 2.8526458211545152218493600470e-03
data8 0xB6BF7564F52140C6, 0x00003FF8 //A6 = 1.1154045718131014476684982178e-02
//
// Polynomial coefficients for the tgammal(x), 0.0 <= |x| < 0.125
//A5 = -9.8199506890314514073736518185e-01+ -5.9363811993837985890950900000e-17
data8 0xBFEF6C80EC38B67A, 0xBC911C46B447C81F
//A4 = 9.8172808683440015986576554496e-01 + 2.7457414262802803699834200000e-17
data8 0x3FEF6A51055096B5, 0x3C7FA7FF90ACAD1F
//A3 = -9.0747907608088618225394839101e-01 + -1.0676255850934306734701780000e-16
data8 0xBFED0A118F324B62, 0xBC9EC5AFB633438D
data8 0x9217E83FA207CB80, 0x00003FFD //A20 = 2.8533864762086088781083621561e-01
data8 0xA8DABFA52FDF03EC, 0x0000BFFE //A19= -6.5958783896337186303285832783e-01
data8 0xE331ED293AF39F9B, 0x00003FFE //A18 = 8.8748056656454687449654731184e-01
data8 0xF9163C5DDB52419D, 0x0000BFFE //A17= -9.7299554149078295602977718525e-01
data8 0xFEC0A1C672CB9265, 0x00003FFE //A16 = 9.9512683005268190987854104489e-01
data8 0xFFD2D65B8EA7B5F4, 0x0000BFFE //A15= -9.9931087241443958201592847861e-01
data8 0xFFF93AA39EE53445, 0x00003FFE //A14 = 9.9989668364186884793382816496e-01
data8 0xFFFB99A9A3F5F480, 0x0000BFFE //A13= -9.9993286506283835663204999212e-01
//A2 = 9.8905599532797250361682017683e-01 + 5.1778575360788420716540100000e-17
data8 0x3FEFA658C23B1578, 0x3C8DD92B45408D07
//A1 = -5.7721566490153275452712478000e-01+ -1.0607938730998824663273110000e-16
data8 0xBFE2788CFC6FB618, 0xBC9E9346F8FDE55B
//A0 = 9.9999999999999988897769753748e-01 + 1.1102230246251564036631420000e-16
data8 0x3FEFFFFFFFFFFFFF, 0x3C9FFFFFFFFFFFFF
data8 0xFFF7FEBB545812C1, 0x00003FFE //A12 = 9.9987785409425126648628395084e-01
data8 0xFFF00C02E943A3F2, 0x0000BFFE //A11= -9.9975657530855116454438747397e-01
data8 0xFFE0420AADC53820, 0x00003FFE //A10 = 9.9951565514290485919027183699e-01
data8 0xFFC01EB42EF27EEB, 0x0000BFFE //A9 = -9.9902526759155739377365522320e-01
data8 0xFF83DAD0BF23FF12, 0x00003FFE //A8 = 9.9810569378236378800364235948e-01
data8 0xFEF9F8ABDBCDB2F3, 0x0000BFFE //A7 = -9.9600176044241699109053158187e-01
data8 0xFE3F05375988491D, 0x00003FFE //A6 = 9.9314911462127599008937257662e-01
LOCAL_OBJECT_END(Constants_Tgammal_poly_splitted)

.align 64
LOCAL_OBJECT_START(Constants_Tgammal_common)
// Positive overflow value
data8 0x3FE0000000000000 // 0.5
data8 0x3FF8000000000000 // 1.5
data8 0x3FD0000000000000 // 0.25
data8 0x0000000000000000 // 0
data8 0xDB718C066B352E21, 0x00004009 // Positive overflow value
LOCAL_OBJECT_END(Constants_Tgammal_common)



//=======================================================
// Lgamma registers

// General Purpose Registers
GR_l_Log_Table        = r33
GR_l_Log_Table1       = r34
GR_l_BIAS             = r34
GR_l_Index1           = r35
GR_l_Index2           = r36
GR_l_signif_Z         = r37
GR_l_X_0              = r38
GR_l_X_1              = r39
GR_l_X_2              = r40
GR_l_Z_1              = r41
GR_l_Z_2              = r42
GR_l_N                = r43
GR_l_Index3           = r44
GR_l_Stirling_Table   = r45
GR_l_N_Unbiased       = r46

// Floating Point Registers
FR_l_logl_X            = f8

FR_l_h_3              = f10
FR_l_poly_hi          = f10
FR_l_W                = f11
FR_l_S                = f12
FR_l_GS_hi            = f13
FR_l_Y_lo             = f13
FR_l_r_cor            = f14
FR_l_G_1              = f15
FR_l_G                = f15
FR_l_H_1              = f32
FR_l_H                = f32
FR_l_h                = f33
FR_l_h_1              = f33
FR_l_N                = f33
FR_l_G_2              = f34
FR_l_H_2              = f35
FR_l_h_2              = f36
FR_l_G_3              = f37
FR_l_log2_hi          = f38
FR_l_GS_lo            = f39
FR_l_H_3              = f40
FR_l_float_N          = f41
FR_l_Q_4              = f42
FR_l_Q_3              = f43
FR_l_Q_2              = f44
FR_l_Q_1              = f45
FR_l_Q_5              = f46
FR_l_Q_6              = f47
FR_l_log2_lo          = f48
FR_l_r                = f49
FR_l_poly_lo          = f50
FR_l_poly             = f51
FR_l_rsq              = f52
FR_l_Y_lo_res         = f53

FR_l_Y0               = f55
FR_l_Q0               = f56
FR_l_E0               = f57
FR_l_E2               = f58
FR_l_E1               = f59
FR_l_Y1               = f60
FR_l_E3               = f61
FR_l_Y2               = f62

FR_l_Z                = f63
FR_l_Z2               = f64
FR_l_Z4               = f65
FR_l_Z8               = f66

FR_l_CH               = f67
FR_l_CL               = f68

FR_l_B2               = f69
FR_l_B4               = f70
FR_l_B6               = f71
FR_l_B8               = f72
FR_l_B10              = f73
FR_l_B12              = f74
FR_l_B14              = f75
FR_l_B16              = f76
FR_l_B18              = f77
FR_l_Half             = f78
FR_l_SS               = f79
FR_l_AbsX_m_Half      = f80
FR_l_CXH              = f81
FR_l_CXL              = f82
FR_l_SSCXH            = f83
FR_l_SSCXL            = f84
FR_l_XYH              = f85
FR_l_XYL              = f86
FR_l_Temp             = f87

FR_l_logl_YHi         = f88
FR_l_logl_YLo         = f89

FR_l_SignedXYH        = f123

FR_l_AbsX             = f127



//=======================================================
// Negative part registers

// General Purpose Registers
GR_n_sin_Table        = r47
GR_n_XN               = r48

// Float point registers
FR_n_IXNS             = f125
FR_n_IXN              = f126

FR_n_XNS              = f90
FR_n_XS               = f91
FR_n_XS2              = f92
FR_n_XS2L             = f93
FR_n_XS4              = f94
FR_n_XS7              = f95
FR_n_XS8              = f96
FR_n_TT               = f97
FR_n_TH               = f98
FR_n_TL               = f99

FR_n_A2H              = f100
FR_n_A2L              = f101
FR_n_A1H              = f102
FR_n_A1L              = f103
FR_n_A9               = f104
FR_n_A8               = f105
FR_n_A7               = f106
FR_n_A6               = f107
FR_n_A5               = f108
FR_n_A4               = f109
FR_n_A3               = f110

FR_n_PolyH            = f111
FR_n_PolyL            = f112

FR_n_Poly1H           = f113
FR_n_SinxH            = f113 // the same as FR_n_Poly1H
FR_n_Poly1L           = f114
FR_n_SinxL            = f114 // the same as FR_n_Poly1L

FR_n_Tail             = f115
FR_n_NegOne           = f116

FR_n_Y0               = f117

FR_n_Q0               = f118
FR_n_E0               = f119

FR_n_E2               = f120
FR_n_E1               = f121

FR_n_Y1               = f55
FR_n_E3               = f56

FR_n_Y2               = f57
FR_n_R0               = f58

FR_n_E4               = f59
FR_n_RcpResH          = f60

FR_n_Y3               = f61
FR_n_R1               = f62
FR_n_Temp             = f63

FR_n_RcpResL          = f64

FR_n_ResH             = f65
FR_n_ResL             = f66




//=======================================================
// Exp registers

// General Purpose Registers
GR_e_ad_Arg           = r33
GR_e_ad_A             = r34
GR_e_signexp_x        = r35
GR_e_exp_x            = r35
GR_e_exp_mask         = r36
GR_e_ad_W1            = r37
GR_e_ad_W2            = r38
GR_e_M2               = r39
GR_e_M1               = r40
GR_e_K                = r41
GR_e_exp_2_mk         = r42
GR_e_exp_2_k          = r43
GR_e_ad_T1            = r44
GR_e_ad_T2            = r45
GR_e_N_fix            = r46
GR_e_one              = r47
GR_e_exp_bias         = r48
GR_e_sig_inv_ln2      = r49
GR_e_rshf_2to51       = r50
GR_e_exp_2tom51       = r51
GR_e_rshf             = r52

// Floating Point Registers
FR_e_RSHF_2TO51       = f10
FR_e_INV_LN2_2TO63    = f11
FR_e_W_2TO51_RSH      = f12
FR_e_2TOM51           = f13
FR_e_RSHF             = f14
FR_e_Y_hi             = f15
FR_e_Y_lo             = f32
FR_e_scale            = f33
FR_e_float_N          = f34
FR_e_N_signif         = f35
FR_e_L_hi             = f36
FR_e_L_lo             = f37
FR_e_r                = f38
FR_e_W1               = f39
FR_e_T1               = f40
FR_e_W2               = f41
FR_e_T2               = f42
FR_e_W1_p1            = f43
FR_e_rsq              = f44
FR_e_A2               = f45
FR_e_r4               = f46
FR_e_A3               = f47
FR_e_poly             = f48
FR_e_T                = f49
FR_e_W                = f50
FR_e_Wp1              = f51
FR_e_r6               = f52
FR_e_2_mk             = f53
FR_e_A1               = f54
FR_e_T_scale          = f55
FR_e_result_lo        = f56
FR_e_W_T_scale        = f57
FR_e_Wp1_T_scale      = f58

FR_e_expl_Input_X     = f123
FR_e_expl_Input_Y     = f124
FR_e_expl_Output_X    = f123
FR_e_expl_Output_Y    = f124


FR_e_expl_Input_AbsX  = f122



//=======================================================
// Common registers

// General Purpose Registers
GR_c_Table            = r53
GR_c_NegUnderflow     = r54
GR_c_NegSingularity   = r55
GR_c_X                = r56
GR_c_SignBit          = r57
GR_c_13               = r58


// Floating Point Registers
FR_c_PosOverflow      = f123
FR_c_XN               = f124


//=======================================================
// Polynomial part registers

// General Purpose Registers
GR_p_Table            = r59
GR_p_XN               = r33
GR_p_Table2           = r34
GR_p_Int              = r35
GR_p_Offset           = r36
GR_p_Offset2          = r38
GR_p_X_Sgnd           = GR_l_signif_Z // = r37
GR_p_Exp              = r61
GR_p_Bias             = r62
GR_p_0p75             = r63

// Floating Point Registers
FR_p_AbsX             = FR_l_AbsX // = f127
FR_p_IXN              = FR_n_IXN  // = f126
FR_p_XN               = f32
FR_p_0p5              = f33
FR_p_1p5              = f34
FR_p_AbsXM1           = f35
FR_p_2                = f36

FR_p_A20              = f37
FR_p_A19              = f38
FR_p_A18              = f39
FR_p_A17              = f40
FR_p_A16              = f41
FR_p_A15              = f42
FR_p_A14              = f43
FR_p_A13              = f44
FR_p_A12              = f45
FR_p_A11              = f46
FR_p_A10              = f47
FR_p_A9               = f48
FR_p_A8               = f49
FR_p_A7               = f50
FR_p_A6               = f51
FR_p_A5H              = f52
FR_p_A5L              = f53
FR_p_A4H              = f54
FR_p_A4L              = f55
FR_p_A3H              = f56
FR_p_A3L              = f57
FR_p_A2H              = f58
FR_p_A2L              = f59
FR_p_A1H              = f60
FR_p_A1L              = f61
FR_p_A0H              = f62
FR_p_A0L              = f63

FR_p_XR               = f64
FR_p_XR2              = f65
FR_p_XR2L             = f52

FR_p_XR3              = f58
FR_p_XR3L             = f38

FR_p_XR4              = f42
FR_p_XR6              = f40
FR_p_XR8              = f37

FR_p_Poly5H           = f66
FR_p_Poly5L           = f67
FR_p_Poly4H           = f53
FR_p_Poly4L           = f44
FR_p_Poly3H           = f41
FR_p_Poly3L           = f47
FR_p_Poly2H           = f68
FR_p_Poly2L           = f54
FR_p_Poly1H           = f55
FR_p_Poly1L           = f46
FR_p_Poly0H           = f39
FR_p_Poly0L           = f43

FR_p_Temp5H           = f69
FR_p_Temp5L           = f70
FR_p_Temp4H           = f71
FR_p_Temp4L           = f60
FR_p_Temp2H           = f72
FR_p_Temp2L           = f73
FR_p_Temp1H           = f59
FR_p_Temp1L           = f61
FR_p_Temp0H           = f49
FR_p_Temp0L           = f48
FR_p_PolyTail         = f45
FR_p_OddPoly0H        = f56
FR_p_OddPoly0L        = f51

FR_p_0p25             = f73


//=======================================================
// Negative polynomial part registers
// General Purpose Registers
GR_r_sin_Table        = r47
GR_r_sin_Table2       = r60

// Floating Point Registers
FR_r_IXNS             = FR_n_IXNS
FR_r_IXN              = FR_n_IXN

FR_r_AbsX             = FR_l_AbsX

FR_r_A9               = f74
FR_r_A8               = f75
FR_r_A7               = f76
FR_r_A6               = f77
FR_r_A5               = f78
FR_r_A4               = f79
FR_r_A3               = f80
FR_r_A2H              = f81
FR_r_A2L              = f82
FR_r_A1H              = f83
FR_r_A1L              = f84

FR_r_XNS              = f85
FR_r_XS               = f86
FR_r_XS2              = f87
FR_r_XS2L             = f88
FR_r_XS4              = f89
FR_r_XS7              = f90
FR_r_XS8              = f91

FR_r_Tail             = f92

FR_r_TT               = f93
FR_r_TH               = f94
FR_r_TL               = f95

FR_r_ResH             = f96
FR_r_ResL             = f97

FR_r_Res3H            = f98
FR_r_Res3L            = f99

FR_r_Res1H            = f100
FR_r_Res1L            = f101



FR_r_Y0               = f102
FR_r_Q0               = f103
FR_r_E0               = f104
FR_r_E2               = f105
FR_r_E1               = f106
FR_r_Y1               = f107
FR_r_E3               = f108
FR_r_Y2               = f109
FR_r_R0               = f110
FR_r_E4               = f111
FR_r_ZH               = f112
FR_r_Y3               = f113
FR_r_R1               = f114
FR_r_ZHN              = f115
FR_r_ZL               = f115
FR_r_NegOne           = f116

FR_z_Y0               = f102
FR_z_Q0               = f103
FR_z_E0               = f104
FR_z_E2               = f105
FR_z_E1               = f106
FR_z_Y1               = f107
FR_z_E3               = f108
FR_z_Y2               = f109
FR_z_R0               = f110
FR_z_E4               = f111
FR_z_ZH               = f112
FR_z_Y3               = f113
FR_z_R1               = f114
FR_z_ZL               = f115


// General Purpose Registers
GR_SAVE_PFS           = r32
GR_DenOverflow        = r33
GR_u_XN               = r34

GR_SAVE_B0            = r35
GR_SAVE_GP            = r36
GR_SAVE_SP            = r37

// Floating Point Registers
FR_u_IXN              = f34


// ERROR HANDLER REGISTERS
GR_Parameter_X        = r64
GR_Parameter_Y        = r65
GR_Parameter_RESULT   = r66
GR_Parameter_TAG      = r67

FR_RESULT             = f8
FR_X                  = f32
FR_Y                  = f1


.section .text
GLOBAL_LIBM_ENTRY(tgammal)
{ .mfi
      alloc         r32            = ar.pfs,0,32,4,0
      fabs          FR_l_AbsX      = f8 // Get absolute value of X
      addl          GR_n_sin_Table = @ltoff(Constants_Tgammal_sin), gp
}
{ .mfi
      addl          GR_l_Log_Table=@ltoff(Constants_Tgammal_log_80_Z_G_H_h1#),gp
      nop.f         0
      addl          GR_l_Stirling_Table = @ltoff(Constants_Tgammal_stirling), gp
};;

{ .mfi
      getf.sig      GR_l_signif_Z  = f8 // Significand of X
      fcvt.fx.s1    FR_n_IXNS      = f8 // Convert to fixed point
      addl          GR_c_Table     = @ltoff(Constants_Tgammal_common), gp
}
{ .mfi
      ld8           GR_l_Log_Table = [GR_l_Log_Table]
      nop.f         0
      addl          GR_p_Table     = @ltoff(Constants_Tgammal_poly), gp
};;

{ .mfi
      ld8           GR_n_sin_Table = [GR_n_sin_Table]
      fclass.m      p6,p0          = f8,0x1EF // Check x for NaN, 0, INF, denorm
                                              // NatVal.
      addl          GR_c_NegSingularity = 0x1003E, r0
}
{ .mlx
      ld8           GR_l_Stirling_Table = [GR_l_Stirling_Table]
      movl          GR_c_13        = 0x402A000000000000 // 13.0
};;

{ .mfi
      getf.d        GR_c_X         = f8 // Double prec. X to general register
      frcpa.s1      FR_z_Y0,p0     = f1,f8 // y = frcpa(x) (for negatives)
      extr.u        GR_l_Index1    = GR_l_signif_Z, 59, 4 // = High 4 bits of Z
}
{ .mlx
      ld8           GR_c_Table     = [GR_c_Table]
      movl          GR_c_SignBit   = 0x8000000000000000 // High bit (sign)
};;

{ .mfi
      ld8           GR_p_Table     = [GR_p_Table]
      fcmp.lt.s1    p15, p14       = f8,f0 // p14 - positive arg, p15 - negative
      shl           GR_l_Index1    = GR_l_Index1,5 // Adjust Index1 ptr (x32)
}
{ .mfb
      adds          GR_c_NegUnderflow = 1765, r0
      nop.f         0
(p6)  br.cond.spnt  tgammal_spec  // Spec. values processing branch ////////////
                                  // (0s, INFs, NANs, NatVals, denormals) //////
};;

{ .mfi
      ldfpd         FR_l_CH,FR_l_CL= [GR_l_Stirling_Table], 16 // Load CH, CL
      fcvt.fx.trunc.s1 FR_n_IXN    = FR_l_AbsX // Abs arg to int by trunc
      extr.u        GR_l_X_0       = GR_l_signif_Z, 49, 15  //  High 15 bit of Z
}
{ .mfi
      add           GR_l_Index1    = GR_l_Index1,GR_l_Log_Table  // Add offset
      fma.s1        FR_p_2         = f1, f1, f1 // 2.0
      andcm         GR_c_X         = GR_c_X, GR_c_SignBit // Remove sign
};;

{ .mfi
      addl       GR_l_Log_Table = @ltoff(Constants_Tgammal_log_80_Z_G_H_h2#), gp
      fcmp.lt.s1    p10, p0        = FR_l_AbsX, f1 // If |X|<1 then p10 = 1
      nop.i         0
}
{ .mlx
      ld2           GR_l_Z_1       = [GR_l_Index1],4 // load Z_1 from Index1
      movl          GR_l_BIAS      = 0x000000000000FFFF // Bias for exponent
};;

{ .mfi
      ld8           GR_l_Log_Table = [GR_l_Log_Table]
      frcpa.s1      FR_l_Y0, p0    = f1, FR_l_AbsX // y = frcpa(x)
      nop.i         0
}
{ .mfi
      ldfs          FR_l_G_1       = [GR_l_Index1],4  //  Load G_1
      fsub.s1       FR_l_W         = FR_l_AbsX, f1 // W = |X|-1
      nop.i         0
};;

{ .mfi
      getf.exp      GR_l_N_Unbiased=  FR_l_AbsX // exponent of |X|
      fmerge.se     FR_l_S         = f1, FR_l_AbsX //  S = merging of X and 1.0
      cmp.gtu       p11, p0        = GR_c_13, GR_c_X // If 1 <= |X| < 13
                                                     // then p11 = 1
}
{ .mfb
      ldfs          FR_l_H_1       = [GR_l_Index1],8 // Load H_1
      fcvt.xf       FR_n_XNS       = FR_n_IXNS // Convert to FP repr. of int X
(p10) br.cond.spnt  tgamma_lt_1    // Branch to |X| < 1 path ///////////////////
};;

{ .mfi
      ldfpd         FR_n_A2H, FR_n_A2L = [GR_n_sin_Table], 16
      nop.f         0
      pmpyshr2.u    GR_l_X_1       = GR_l_X_0,GR_l_Z_1,15 // Adjust Index2 (x32)
}
{ .mfb
      ldfe          FR_l_B2        = [GR_l_Stirling_Table], 16
      nop.f         0
(p11) br.cond.spnt  tgamma_lt_13 // Branch to 1 <= |X| < 13 path ///////////////
};;

{ .mfi
      ldfe          FR_l_h_1       = [GR_l_Index1],0
      nop.f         0
      sub           GR_l_N         = GR_l_N_Unbiased, GR_l_BIAS  //  N - BIAS
}
{ .mib
      ldfpd         FR_l_B4,FR_l_B6= [GR_l_Stirling_Table], 16 // Load C
(p15) cmp.geu.unc   p8,p0          = GR_l_N_Unbiased, GR_c_NegSingularity
(p8)  br.cond.spnt  tgammal_singularity // Singularity for arg < to -2^63 //////
};;

{ .mmi
(p15) ldfpd         FR_n_A1H, FR_n_A1L = [GR_n_sin_Table], 16
      ldfpd         FR_l_B8, FR_l_B10  = [GR_l_Stirling_Table], 16
      add           GR_c_Table         = 0x20, GR_c_Table
};;

{ .mfi
(p15) ldfe          FR_n_A9        = [GR_n_sin_Table], 16
      fma.s1        FR_l_Q0        = f1,FR_l_Y0,f0 // Q0 = Y0
      nop.i         0
}
{ .mfi
      ldfpd         FR_l_B12, FR_l_B14 = [GR_l_Stirling_Table], 16
      fnma.s1       FR_l_E0        = FR_l_Y0,FR_l_AbsX,f1 // e = 1-b*y
      nop.i         0
};;

{ .mfi
(p15) ldfe          FR_n_A8        = [GR_n_sin_Table], 16
      fcvt.xf       FR_c_XN        = FR_n_IXN // Convert to FP repr. of int X
      extr.u        GR_l_Index2    = GR_l_X_1, 6, 4  // Extract Index2
}
{ .mfi
      ldfpd         FR_l_B16, FR_l_B18 = [GR_l_Stirling_Table], 16
      nop.f         0
      nop.i         0
};;

{ .mfi
(p15) ldfe          FR_n_A7        = [GR_n_sin_Table], 16
      fms.s1        FR_l_CXH       = FR_l_CH, f1, FR_l_AbsX // CXH = CH+|X|
      shl           GR_l_Index2    = GR_l_Index2,5
}
{ .mfi
      ldfd          FR_l_Half      = [GR_l_Stirling_Table] // Load 0.5
      nop.f         0
      nop.i         0
};;

{ .mfi
      add           GR_l_Index2    = GR_l_Index2, GR_l_Log_Table  // Add offset
      nop.f         0
      nop.i         0
}
{ .mfi
(p15) ldfe          FR_n_A6        = [GR_n_sin_Table], 16
(p15) fma.s1        FR_n_XS        = FR_l_AbsX , f1, FR_n_XNS // xs = x - int(x)
      nop.i         0
};;

{ .mmi
      ld2           GR_l_Z_2       = [GR_l_Index2],4
      addl          GR_l_Log_Table = @ltoff(Constants_Tgammal_log_80_h3_G_H#),gp
      nop.i         0
};;

{ .mfi
      ld8           GR_l_Log_Table = [GR_l_Log_Table]
      fma.s1        FR_l_E2        = FR_l_E0,FR_l_E0,FR_l_E0 // e2 = e+e^2
      nop.i         0
}
{ .mfi
      ldfs          FR_l_G_2       = [GR_l_Index2],4
      fma.s1        FR_l_E1        = FR_l_E0,FR_l_E0,f0 // e1 = e^2
      nop.i         0
};;

{ .mmi
      ldfs          FR_l_H_2       = [GR_l_Index2],8
(p15) ldfe          FR_n_A5        = [GR_n_sin_Table], 16
      nop.i         0
};;

{ .mfi
      setf.sig      FR_l_float_N   = GR_l_N //    float_N = Make N a fp number
      nop.f         0
      pmpyshr2.u    GR_l_X_2       = GR_l_X_1,GR_l_Z_2,15  // X_2 = X_1 * Z_2
}
{ .mfi
      ldfe          FR_l_h_2       = [GR_l_Index2],0
      fma.s1        FR_l_CXL       = FR_l_AbsX, f1, FR_l_CXH // CXL = |X|+CXH
      add           GR_l_Log_Table1= 0x200, GR_l_Log_Table
};;

{ .mfi
(p15) ldfe          FR_n_A4        = [GR_n_sin_Table], 16
(p15) fcmp.eq.unc.s1 p9,p0         = FR_l_AbsX, FR_c_XN //if argument is integer
                                                        // and negative
      nop.i         0
}
{ .mfi
      ldfe          FR_c_PosOverflow = [GR_c_Table],16 //Load pos overflow value
(p15) fma.s1        FR_n_XS2         = FR_n_XS, FR_n_XS, f0 // xs^2 = xs*xs
      nop.i         0
};;

{ .mfi
(p15) ldfe          FR_n_A3        = [GR_n_sin_Table], 16
      nop.f         0
      nop.i         0
};;

{ .mfi
(p15) getf.sig      GR_n_XN        = FR_n_IXN // int(x) to general reg
      fma.s1        FR_l_Y1        = FR_l_Y0,FR_l_E2,FR_l_Y0 // y1 = y+y*e2
      nop.i         0
}
{ .mfb
      nop.m         0
      fma.s1        FR_l_E3        = FR_l_E1,FR_l_E1,FR_l_E0 // e3 = e+e1^2
(p9)  br.cond.spnt  tgammal_singularity // Singularity for integer /////////////
                                        // and negative arguments //////////////
};;

{ .mfi
      nop.m         0
      fms.s1        FR_l_AbsX_m_Half = FR_l_AbsX, f1, FR_l_Half // |x|-0.5
      extr.u        GR_l_Index2      = GR_l_X_2, 1, 5   //  Get Index3
};;

{ .mfi
      shladd        GR_l_Log_Table1= GR_l_Index2, 2, GR_l_Log_Table1
      nop.f         0
      shladd        GR_l_Index3    = GR_l_Index2,4, GR_l_Log_Table  // Index3
}
{ .mfb
(p15) cmp.gtu.unc   p11, p0        = GR_n_XN, GR_c_NegUnderflow // X < -1765
      fms.s1        FR_l_CXL       = FR_l_CH, f1, FR_l_CXL // CXL = CH - CXL
(p11) br.cond.spnt tgammal_underflow // Singularity for negative argument //////
                                     // at underflow domain (X < -1765) //////
};;

{ .mfi
      addl          GR_l_Log_Table = @ltoff(Constants_Tgammal_log_80_Q#), gp
(p15) fma.s1        FR_n_TT        = FR_n_A2L, FR_n_XS2, f0 // T=A2L*x^2
      tbit.nz.unc   p13, p12       = GR_n_XN, 0x0 // whether [X] odd or even
}
{ .mfi
      nop.m         0
(p15) fms.s1        FR_n_XS2L      = FR_n_XS, FR_n_XS, FR_n_XS2 // xs^2 Low part
      nop.i         0
};;

{ .mfi
      ld8           GR_l_Log_Table = [GR_l_Log_Table]
(p15) fma.s1        FR_n_A7        = FR_n_A8,  FR_n_XS2, FR_n_A7 // poly tail
      nop.i 0
}
{ .mfi
      ldfe          FR_l_h_3       = [GR_l_Index3],12
(p15) fma.s1        FR_n_XS4       = FR_n_XS2, FR_n_XS2, f0 // xs^4 = xs^2*xs^2
      nop.i 0
};;

{ .mfi
      ldfs          FR_l_H_3       = [GR_l_Log_Table1], 0
      fma.s1        FR_l_Y2        = FR_l_Y1, FR_l_E3, FR_l_Y0 // y2 = y+y1*e3
      nop.i         0
}
{ .mfi
      ldfs          FR_l_G_3       = [GR_l_Index3], 0
      fnma.s1       FR_l_Z         = FR_l_AbsX,FR_l_Q0,f1 // r = a-b*q
      nop.i         0
};;

{ .mfi
      nop.m         0
      fmpy.s1       FR_l_G         = FR_l_G_1, FR_l_G_2 // G = G1 * G_2
      nop.i         0
}
{ .mfi
      nop.m         0
      fadd.s1       FR_l_H         = FR_l_H_1, FR_l_H_2 // H = H_1 + H_2
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_log2_hi   = [GR_l_Log_Table],16 //  load log2_hi part
      fadd.s1       FR_l_h         = FR_l_h_1, FR_l_h_2  //  h = h_1 + h_2
      nop.i         0
}
{ .mfi
      nop.m         0
      fcvt.xf       FR_l_float_N   = FR_l_float_N // int(N)
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_log2_lo   = [GR_l_Log_Table],16 //  Load log2_lo part
      fma.s1        FR_l_CXL       = FR_l_CXL, f1, FR_l_CL
      nop.i 0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_TT        = FR_n_A2H, FR_n_XS2L, FR_n_TT // T=A2H*x2L+T
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_Q_6       = [GR_l_Log_Table],16
(p15) fma.s1        FR_n_A3        = FR_n_A4,  FR_n_XS2, FR_n_A3 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_A5        = FR_n_A6,  FR_n_XS2, FR_n_A5 // poly tail
      nop.i 0
};;

{ .mfi
      ldfe          FR_l_Q_5       = [GR_l_Log_Table],16
(p15) fabs          FR_n_XS        = FR_n_XS // abs(xs)
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_Z         = FR_l_Z,FR_l_Y2,FR_l_Q0 // x_hi = q+r*y2
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_Q_4       = [GR_l_Log_Table],16
(p15) fma.s1        FR_n_A7        = FR_n_A9,  FR_n_XS4, FR_n_A7 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_XS7       = FR_n_XS4, FR_n_XS2, f0 // = x^4*x^2
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_Q_3       = [GR_l_Log_Table],16
      fneg          FR_n_NegOne    = f1 // -1.0
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_XS8       = FR_n_XS4, FR_n_XS4, f0 // xs^8 = xs^4*xs^4
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_Q_2       = [GR_l_Log_Table],16
      fadd.s1       FR_l_h         = FR_l_h, FR_l_h_3 //  h = h_1 + h_2 + h_3
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_TH        = FR_n_A2H, FR_n_XS2, FR_n_TT // A2H*xs2+T
      nop.i         0
};;

{ .mfi
      ldfe          FR_l_Q_1       = [GR_l_Log_Table],16
      fmpy.s1       FR_l_G         = FR_l_G, FR_l_G_3 // G = G_1 * G_2 * G_3
      nop.i         0
}
{ .mfi
      nop.m         0
      fadd.s1       FR_l_H         = FR_l_H, FR_l_H_3 // H = H_1 + H_2 + H_3
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_Z2        = FR_l_Z, FR_l_Z, f0 // Z^2
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_A3        = FR_n_A5,  FR_n_XS4, FR_n_A3 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
(p14) fcmp.gt.unc.s1 p7,p0         = FR_l_AbsX, FR_c_PosOverflow //X > 1755.5483
              // (overflow domain, result cannot be represented by normal value)
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_XS7       = FR_n_XS7, FR_n_XS,  f0 // x^7 construction
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fms.s1        FR_n_TL        = FR_n_A2H, FR_n_XS2, FR_n_TH // A2H*xs2+TH
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_PolyH     = FR_n_TH, f1, FR_n_A1H // PolyH=TH+A1H
      nop.i         0
};;

{ .mfi
      nop.m         0
      fmpy.s1       FR_l_GS_hi     = FR_l_G, FR_l_S // GS_hi = G*S
      nop.i         0
}
{ .mfb
      nop.m         0
      fms.s1        FR_l_r         = FR_l_G, FR_l_S, f1 // r = G*S -1
(p7)  br.cond.spnt  tgammal_overflow // Overflow path for arg > 1755.5483 //////
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_B14       = FR_l_B16, FR_l_Z2, FR_l_B14// Bernoulli tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_Z4        = FR_l_Z2, FR_l_Z2, f0 // Z^4 = Z^2*Z^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_B2        = FR_l_B4, FR_l_Z2, FR_l_B2 // Bernoulli tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_B6        = FR_l_B8, FR_l_Z2, FR_l_B6 // Bernoulli tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_B10       = FR_l_B12, FR_l_Z2, FR_l_B10// Bernoulli tail
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_Tail      = FR_n_A7,  FR_n_XS8, FR_n_A3 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_TL        = FR_n_TL, f1, FR_n_TT // TL = TL+T
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fms.s1        FR_n_PolyL     = FR_n_A1H, f1, FR_n_PolyH // polyH+A1H
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_poly_lo   = FR_l_r, FR_l_Q_6, FR_l_Q_5 // Q_5+r*Q_6
      nop.i         0
}
{ .mfi
      nop.m         0
      fsub.s1       FR_l_r_cor     = FR_l_GS_hi, f1 //     r_cor = GS_hi -1
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_l_GS_lo     = FR_l_G, FR_l_S, FR_l_GS_hi // G*S-GS_hi
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_poly      = FR_l_r, FR_l_Q_2, FR_l_Q_1 //poly=r*Q2+Q1
      nop.i         0
};;

{ .mfi
      nop.m         0
      fmpy.s1       FR_l_rsq       = FR_l_r, FR_l_r // rsq = r * r
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_G         = FR_l_float_N, FR_l_log2_hi, FR_l_H // Tbl =
                                                        // float_N*log2_hi + H
      nop.i         0
};;

{ .mfi
      nop.m 0
      fma.s1        FR_l_Y_lo      = FR_l_float_N, FR_l_log2_lo, FR_l_h // Y_lo=
                                                       // float_N*log2_lo + h
      nop.i 0
}
{ .mfi
      nop.m 0
      fma.s1        FR_l_B14       = FR_l_B18, FR_l_Z4, FR_l_B14 //bernulli tail
      nop.i 0
};;

{ .mfi
      nop.m 0
      fma.s1        FR_l_B2        = FR_l_B6, FR_l_Z4, FR_l_B2 //bernulli tail
      nop.i 0
}
{ .mfi
      nop.m 0
      fma.s1        FR_l_Z8        = FR_l_Z4, FR_l_Z4, f0 //bernulli tail
      nop.i 0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_poly_lo   = FR_l_r, FR_l_poly_lo, FR_l_Q_4 // poly_lo =
                                                            // Q_4 + r * poly_lo
      nop.i         0
}
{ .mfi
      nop.m         0
      fsub.s1       FR_l_r_cor     = FR_l_r_cor, FR_l_r // r_cor = r_cor - r
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_PolyL     = FR_n_PolyL, f1, FR_n_TH // polyL+TH
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_TT        = FR_n_TL, f1, FR_n_A1L // TL+A1L
      nop.i         0
};;

{ .mfi
      nop.m         0
      fadd.s1       FR_l_logl_YHi  = FR_l_G, FR_l_r // Y_hi = Tbl + r
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_B10       = FR_l_B14, FR_l_Z4, FR_l_B10 //bernulli tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_poly_lo   = FR_l_r, FR_l_poly_lo, FR_l_Q_3 // poly_lo =
                                                          // Q_3 + r * poly_lo
      nop.i         0
}
{ .mfi
      nop.m         0
      fadd.s1       FR_l_r_cor     = FR_l_r_cor, FR_l_GS_lo // r_cor=r_cor+GS_lo
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_PolyL     = FR_n_PolyL, f1, FR_n_TT // polyL+TT
      nop.i         0
};;

{ .mfi
      nop.m         0
      fsub.s1       FR_l_Y_lo_res  = FR_l_G, FR_l_logl_YHi // Y_lo = Tbl - Y_hi
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_XYH       = FR_l_logl_YHi, FR_l_AbsX_m_Half, f0 // XYH=
                                          // YHi*|x-0.5|
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_SS        = FR_l_B10, FR_l_Z8, FR_l_B2 // Bernoulli tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fadd.s1       FR_l_r_cor     = FR_l_r_cor, FR_l_Y_lo // r_cor = r_cor+Y_lo
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_l_poly      = FR_l_rsq, FR_l_poly_lo, FR_l_poly //poly=
                                                            // r^2*polyLo+poly
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_TT        = FR_n_PolyL, FR_n_XS2, f0 // T=polyL*xs^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fadd.s1       FR_l_Y_lo      = FR_l_Y_lo_res, FR_l_r // Y_lo =  Y_lo + r
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_l_XYL       = FR_l_logl_YHi, FR_l_AbsX_m_Half, FR_l_XYH
                                                      // XYL = YHi*|x-0.5|-XYH
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_SSCXH     = FR_l_SS, FR_l_Z, FR_l_CXH // SS*Z+CXH
      nop.i         0
}
{ .mfi
      mov           GR_e_exp_2tom51= 0xffff-51 // 2^-51
(p15) fma.s1        FR_l_SignedXYH = FR_l_XYH, FR_n_NegOne, f0 // XYH = -XYH
                                                            // for negatives
      nop.i         0
};;

{ .mlx
      nop.m         0
      movl          GR_e_rshf_2to51  = 0x4718000000000000   // 1.10000 2^(63+51)
}
{ .mlx
      nop.m         0
      movl          GR_e_sig_inv_ln2 = 0xb8aa3b295c17f0bc //significand of 1/ln2
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_poly      = FR_l_rsq, FR_l_poly, FR_l_r_cor // poly =
                                                        // rsq * poly + r_cor
      nop.i         0
};;

{ .mfi
      addl          GR_e_ad_Arg    = @ltoff(Constants_Tgammal_exp_64_Arg#),gp
(p15) fma.s1        FR_n_TT        = FR_n_PolyH, FR_n_XS2L, FR_n_TT
      mov           GR_e_exp_mask  = 0x1FFFF          // Form exponent mask
}
{ .mlx
      nop.m         0
      movl          GR_e_rshf      = 0x43e8000000000000  // 1.10000 2^63 rshift
};;


{ .mmi
      setf.sig      FR_e_INV_LN2_2TO63 = GR_e_sig_inv_ln2 // form 1/ln2 * 2^63
      setf.d        FR_e_RSHF_2TO51    = GR_e_rshf_2to51 //  1.1000 * 2^(63+51)
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_l_SSCXL     = FR_l_CXH, f1, FR_l_SSCXH // CXH+SS*CXH
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_e_expl_Input_AbsX = FR_l_XYH, f1, FR_l_SSCXH // HI EXP
      nop.i         0
};;

.pred.rel "mutex",p14,p15
{ .mfi
      nop.m         0
(p14) fma.s1        FR_e_expl_Input_X = FR_l_XYH, f1, FR_l_SSCXH // HI EXP
      mov           GR_e_exp_bias     = 0x0FFFF  // Set exponent bias
}
{ .mfi
      ld8           GR_e_ad_Arg       = [GR_e_ad_Arg] // Point to Arg table
(p15) fms.s1        FR_e_expl_Input_X = FR_l_SignedXYH, f1, FR_l_SSCXH // HI EXP
      nop.i         0
};;

{ .mfi
      nop.m         0
      fadd.s1       FR_l_logl_YLo  = FR_l_Y_lo, FR_l_poly // YLo = YLo+poly
      nop.i         0
};;

{ .mfi
      setf.exp      FR_e_2TOM51    = GR_e_exp_2tom51 //2^-51 for scaling float_N
(p15) fma.s1        FR_n_TH        = FR_n_PolyH, FR_n_XS2, FR_n_TT // TH=
                                                           // polyH*xs^2+T
      nop.i         0
}
{ .mib
      setf.d        FR_e_RSHF     = GR_e_rshf // Right shift const 1.1000*2^63
      nop.i 0
      nop.b 0
};;

{ .mfi
      add           GR_e_ad_A      = 0x20, GR_e_ad_Arg // Point to A table
      nop.f         0
      add           GR_e_ad_T1     = 0x50, GR_e_ad_Arg // Point to T1 table
}
{ .mfi
      add           GR_e_ad_T2     = 0x150, GR_e_ad_Arg // Point to T2 table
      nop.f         0
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_SSCXL     =   FR_l_SS, FR_l_Z,  FR_l_SSCXL
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_e_expl_Input_Y = FR_l_XYH, f1, FR_e_expl_Input_AbsX
      nop.i         0
};;

{ .mfi
      ldfe          FR_e_L_hi      = [GR_e_ad_Arg],16 // Get L_hi
      nop.f         0
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_XYL       = FR_l_logl_YLo, FR_l_AbsX_m_Half, FR_l_XYL
                                                     // XYL = YLo*|x-0.5|+XYL
      nop.i         0
};;

{ .mfi
      ldfe          FR_e_L_lo      = [GR_e_ad_Arg],16     // Get L_lo
(p15) fms.s1        FR_n_TL        = FR_n_PolyH, FR_n_XS2, FR_n_TH // TL =
                                                          // = polyH*xs^2-TH
      add           GR_e_ad_W1     = 0x100, GR_e_ad_T2   // Point to W1 table
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_Poly1H    = FR_n_TH, f1, f1 // poly1H = TH+1
      add           GR_e_ad_W2     = 0x300, GR_e_ad_T2 // Point to W2 table
};;

{ .mmi
      getf.exp      GR_e_signexp_x = FR_e_expl_Input_X // Extract sign and exp
      ldfe          FR_e_A3        = [GR_e_ad_A],16     // Get A3
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_SSCXL     = FR_l_SSCXL, f1, FR_l_CXL
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_e_expl_Input_Y = FR_e_expl_Input_Y, f1, FR_l_SSCXH
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1  FR_e_N_signif=FR_e_expl_Input_X,FR_e_INV_LN2_2TO63,FR_e_RSHF_2TO51
      and           GR_e_exp_x     = GR_e_signexp_x, GR_e_exp_mask
};;

{ .mmi
      sub           GR_e_exp_x     = GR_e_exp_x, GR_e_exp_bias // Get exponent
      ldfe          FR_e_A2        = [GR_e_ad_A],16     // Get A2 for main path
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_PolyH     =    FR_n_Poly1H, FR_n_XS, f0//sin(Pi*x) poly
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fms.s1        FR_n_Poly1L    =    f1, f1, FR_n_Poly1H//sin(Pi*x) poly
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_TL        =    FR_n_TL, f1, FR_n_TT//sin(Pi*x) poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_l_Temp      =   FR_l_XYL, f1, FR_l_SSCXL // XYL+SS*CXL
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fma.s1        FR_e_expl_Input_Y = FR_e_expl_Input_Y, FR_n_NegOne, f0
                     // Negate lo part of exp argument for negative input values
      nop.i         0
};;

{ .mfi
      ldfe          FR_e_A1        = [GR_e_ad_A],16   // Get A1
      nop.f         0
      nop.i         0
}
{ .mfi
      nop.m 0
      fms.s1        FR_e_float_N   = FR_e_N_signif, FR_e_2TOM51, FR_e_RSHF
                                           // Get float N = signd*2^51-RSHIFTER
      nop.i 0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_Poly1L    = FR_n_Poly1L, f1, FR_n_TH //sin(Pi*x) poly
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fms.s1        FR_n_PolyL     = FR_n_Poly1H, FR_n_XS, FR_n_PolyH//sin(Pi*x)
      nop.i         0
};;

{ .mfi
      getf.sig      GR_e_N_fix     = FR_e_N_signif // Get N from significand
      nop.f         0
      nop.i         0
};;

.pred.rel "mutex",p14,p15
{ .mfi
      nop.m 0
(p14) fma.s1        FR_e_expl_Input_Y = FR_e_expl_Input_Y, f1, FR_l_Temp
      nop.i         0
}
{ .mfi
      nop.m 0
(p15) fms.s1        FR_e_expl_Input_Y = FR_e_expl_Input_Y, f1, FR_l_Temp
      // arguments for exp computation
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_e_r         = FR_e_L_hi, FR_e_float_N, FR_e_expl_Input_X
                                                   // r = -L_hi * float_N + x
      extr.u        GR_e_M1        = GR_e_N_fix, 6, 6   // Extract index M_1
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_Poly1L    =   FR_n_Poly1L, f1, FR_n_TL //sin(Pi*x) poly
      nop.i         0
};;


{ .mmf
      nop.m         0
      nop.m         0
      fma.s1        FR_e_r         = FR_e_r, f1, FR_e_expl_Input_Y
                                                 // r =  r + FR_e_expl_Input_Y
};;

{ .mmi
      shladd        GR_e_ad_W1     = GR_e_M1,3,GR_e_ad_W1 // Point to W1
      shladd        GR_e_ad_T1     = GR_e_M1,2,GR_e_ad_T1 // Point to T1
      extr.u        GR_e_M2        = GR_e_N_fix, 0, 6      // Extract index M_2
};;


{ .mfi
      ldfs          FR_e_T1        = [GR_e_ad_T1],0         // Get T1
      nop.f         0
      extr          GR_e_K         = GR_e_N_fix, 12, 32 //Extract limit range K
}
{ .mfi
      shladd        GR_e_ad_T2     = GR_e_M2,2,GR_e_ad_T2 // Point to T2
(p15) fma.s1        FR_n_PolyL     = FR_n_Poly1L, FR_n_XS, FR_n_PolyL
                                                              //sin(Pi*x) poly
      shladd        GR_e_ad_W2     = GR_e_M2,3,GR_e_ad_W2 // Point to W2
};;

{ .mfi
      ldfs          FR_e_T2        = [GR_e_ad_T2],0         // Get T2
      nop.f         0
      add           GR_e_exp_2_k   = GR_e_exp_bias, GR_e_K // exp of 2^k
}
{ .mfi
      ldfd          FR_e_W1        = [GR_e_ad_W1],0         // Get W1
      nop.f         0
      sub           GR_e_exp_2_mk  = GR_e_exp_bias, GR_e_K // exp of 2^-k
};;

{ .mmi
      ldfd          FR_e_W2        = [GR_e_ad_W2],0         // Get W2
      nop.m 0
      nop.i 0
};;

{ .mmf
      setf.exp      FR_e_scale     = GR_e_exp_2_k     // Set scale = 2^k
      setf.exp      FR_e_2_mk      = GR_e_exp_2_mk     // Form 2^-k
      fnma.s1       FR_e_r         = FR_e_L_lo, FR_e_float_N, FR_e_r
                                               // r = -L_lo * float_N + r
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_PolyL     = FR_n_Tail, FR_n_XS7, FR_n_PolyL
                                                               //sin(Pi*x) poly
      nop.i         0
};;

{ .mfi
      nop.m 0
      fma.s1        FR_e_poly      = FR_e_r, FR_e_A3, FR_e_A2 // poly=r*A3+A2
      nop.i 0
}
{ .mfi
      nop.m 0
      fmpy.s1       FR_e_rsq       = FR_e_r, FR_e_r // rsq = r * r
      nop.i 0
};;

{ .mfi
      nop.m 0
      fmpy.s1       FR_e_T         = FR_e_T1, FR_e_T2         // T = T1 * T2
      nop.i 0
}
{ .mfi
      nop.m 0
      fadd.s1       FR_e_W1_p1     = FR_e_W1, f1        // W1_p1 = W1 + 1.0
      nop.i 0
};;

{ .mfi
      nop.m 0
(p15) fma.s1        FR_n_TT        = FR_n_PolyL, FR_l_AbsX, f0 //sin(Pi*x) poly
      nop.i 0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_e_poly      = FR_e_r, FR_e_poly, FR_e_A1
                                                 // poly = r * poly + A1
      nop.i 0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_e_T_scale   = FR_e_T, FR_e_scale, f0 // T_scale=T*scale
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_e_W         = FR_e_W2, FR_e_W1_p1, FR_e_W1
                                                     // W = W2 * (W1+1.0) + W1
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_SinxH     =    FR_n_PolyH, FR_l_AbsX, FR_n_TT
                                                              // sin(Pi*x) poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      mov           FR_e_Y_hi      = FR_e_T  // Assume Y_hi = T
      nop.i         0
};;

{ .mfi
      nop.m 0
      fma.s1        FR_e_poly      = FR_e_rsq, FR_e_poly, FR_e_r
                                                     // poly = rsq * poly + r
      nop.i 0
};;

{ .mfi
      nop.m 0
      fma.s1        FR_e_Wp1_T_scale = FR_e_W, FR_e_T_scale, FR_e_T_scale
                                                              // (W+1)*T*scale
      nop.i 0
}
{ .mfi
      nop.m 0
      fma.s1        FR_e_W_T_scale = FR_e_W, FR_e_T_scale, f0 // W*T*scale
      nop.i 0
};;

{ .mfi
      nop.m 0
(p15) fms.s1        FR_n_SinxL     =   FR_n_PolyH, FR_l_AbsX, FR_n_SinxH
                                                             // Low part of sin
      nop.i 0
};;

{ .mfi
      nop.m         0
(p15) frcpa.s1      FR_n_Y0, p0    = f1, FR_n_SinxH //  y = frcpa(b)
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_e_result_lo = FR_e_Wp1_T_scale, FR_e_poly, FR_e_W_T_scale
                                                       // Low part of exp result
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_SinxL     = FR_n_SinxL, f1, FR_n_TT // sin low result
      nop.i         0
};;

{ .mfi
      nop.m         0
(p15) fma.s1        FR_n_Q0        = f1,FR_n_Y0,f0 // q = y
      nop.i         0
}
{ .mfi
      nop.m         0
(p15) fnma.s1       FR_n_E0        = FR_n_Y0, FR_n_SinxH, f1 // e = 1-b*y
      nop.i         0
};;


{ .mfb
      nop.m         0
(p14) fma.s0        f8             = FR_e_Y_hi, FR_e_scale, FR_e_result_lo
(p14) br.ret.spnt   b0 // Exit for positive Stirling path //////////////////////
};;

{ .mfi
      nop.m 0
      fma.s1        FR_e_expl_Output_X = FR_e_Y_hi, FR_e_scale, f0 // exp result
      nop.i         0
}
{ .mfi
      nop.m 0
      fma.s1        FR_e_expl_Output_Y = FR_e_result_lo, f1, f0// exp lo result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_E2        = FR_n_E0,FR_n_E0,FR_n_E0 //  e2 = e+e^2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_n_E1        = FR_n_E0,FR_n_E0,f0 //  e1 = e^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_Y1        = FR_n_Y0,FR_n_E2,FR_n_Y0 //  y1 = y+y*e2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_n_E3        = FR_n_E1,FR_n_E1,FR_n_E0 //  e3 = e+e1^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_Y2        = FR_n_Y1,FR_n_E3,FR_n_Y0 //  y2 = y+y1*e3
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_n_R0        = FR_n_SinxH,FR_n_Q0,f1 //  r = a-b*q
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_n_E4        = FR_n_SinxH,FR_n_Y2,f1 //  e4 = 1-b*y2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_n_RcpResH   = FR_n_R0,FR_n_Y2,FR_n_Q0 //  x = q+r*y2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_Y3        = FR_n_Y2,FR_n_E4,FR_n_Y2 //  y3 = y2+y2*e4
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_n_R1        = FR_n_SinxH,FR_n_RcpResH,f1 //  r1 = a-b*x
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_n_R1        = FR_n_SinxL,FR_n_RcpResH,FR_n_R1
                                                          // r1 = r1 - b_lo*X
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_RcpResL   = FR_n_R1,FR_n_Y3,f0 //  x_lo = r1*y3
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_n_Temp      = FR_n_RcpResH, FR_e_expl_Output_Y, f0
                                              // Multiplying exp and sin result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_Temp      = FR_n_RcpResL, FR_e_expl_Output_X, FR_n_Temp
                                              // Multiplying exp and sin result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_ResH      = FR_n_RcpResH, FR_e_expl_Output_X, FR_n_Temp
                                              // Multiplying exp and sin result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_n_ResL      = FR_n_RcpResH, FR_e_expl_Output_X, FR_n_ResH
                                              // Multiplying exp and sin result
      nop.i         0
}
{ .mfi
      nop.m         0
(p12) fma.s1        FR_n_ResH      = FR_n_ResH, FR_n_NegOne, f0 // Negate
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_n_ResL  = FR_n_ResL, f1, FR_n_Temp
                      // Multiplying exp and sin result - low result obtained
      nop.i         0
};;

.pred.rel "mutex",p12,p13
{ .mfi
      nop.m         0
(p13) fma.s0        f8             = FR_n_ResH, f1, FR_n_ResL // For odd
      nop.i         0
}
{ .mfb
      nop.m         0
(p12) fms.s0        f8             = FR_n_ResH, f1, FR_n_ResL // For even
      br.ret.sptk   b0 // Exit for negative Stirling path //////////////////////
};;


//////////// 1 <= |X| < 13 path ////////////////////////////////////////////////
//------------------------------------------------------------------------------
.align 64
tgamma_lt_13:
{ .mfi
      getf.sig      GR_p_XN        = FR_p_IXN // Get significand
      fcvt.xf       FR_p_XN        = FR_p_IXN  // xn = [x]
      add           GR_r_sin_Table2= 0x40, GR_r_sin_Table // Shifted table addr.
}
{ .mfi
      ldfpd         FR_p_0p5, FR_p_1p5 = [GR_c_Table], 16  // 0.5 & 1.5
      fms.s1        FR_p_AbsXM1    = FR_p_AbsX, f1, f1 // X-1
      add           GR_p_Table2    = 0xB0, GR_p_Table
};;

{ .mfi
      add           GR_r_sin_Table = -16, GR_r_sin_Table // For compensation
      fcvt.xf       FR_r_XNS       = FR_r_IXNS // Convert int repr to float
      shr.u         GR_p_X_Sgnd    = GR_p_X_Sgnd, 59 // Get only 5 bit of signd
};;

{ .mfi
      ldfpd         FR_r_A2H,FR_r_A2L = [GR_r_sin_Table], 16 // Load A2
      nop.f         0
      add           GR_p_Int       = -2, GR_p_XN // int = int - 2
}
{ .mfi
      ldfe          FR_r_A6 = [GR_r_sin_Table2], 16
      nop.f         0
      cmp.gtu       p11, p12 = 0x2, GR_p_XN // p11: x < 2 (splitted intervals),
                                            // p12: x > 2 (base intervals)
};;

{ .mfi
      ldfpd         FR_r_A1H, FR_r_A1L = [GR_r_sin_Table], 16
      nop.f         0
      shr           GR_p_Int       = GR_p_Int, 1 // int/2
}
{ .mfi
      ldfe          FR_r_A5        = [GR_r_sin_Table2], 16
      nop.f         0
(p11) cmp.gtu.unc   p10, p11       = 0x1C, GR_p_X_Sgnd // sgnd(x) < 0.75
};;

{ .mfi
      ldfe          FR_r_A9        = [GR_r_sin_Table], 16
      nop.f         0
      shl           GR_p_Offset    = GR_p_Int, 4 // offset = int*16
}
{ .mfi
      ldfe          FR_r_A4        = [GR_r_sin_Table2], 16
      nop.f         0
(p10) cmp.gtu.unc   p9, p10        = 0x14, GR_p_X_Sgnd // sgnd(x) < 0.25
};;


{ .mfi
      ldfe          FR_r_A8        = [GR_r_sin_Table], 16
      nop.f         0
(p12) tbit.nz.unc   p13, p12       = GR_p_XN, 0x0 // p13: reccurent computations
                                      // X is at [3;4], [5;6], [7;8]... interval
}
{ .mfi
      ldfe          FR_r_A3        = [GR_r_sin_Table2], 16
      nop.f         0
      shladd        GR_p_Offset    = GR_p_Int, 2, GR_p_Offset // +int*4
};;

.pred.rel "mutex",p9,p11
{ .mfi
      add           GR_p_Offset    = GR_p_Int, GR_p_Offset
                                                    // +int, so offset = int*21
(p9)  fms.s1        FR_p_XR        = FR_p_AbsX, f1, f1 // r = x-1
      nop.i         0
}
{ .mfi
      ldfe          FR_r_A7        = [GR_r_sin_Table], 16
(p11) fms.s1        FR_p_XR        = FR_p_2, f1, FR_p_AbsX
                                                    // r = 2-x for 1.75 < x < 2
      nop.i         0
};;

.pred.rel "mutex",p9,p10
.pred.rel "mutex",p10,p11
.pred.rel "mutex",p9,p11
{ .mfi
(p9)  add           GR_p_Offset    = 126, r0 // 1.0 < x < 1.25 table
(p15) fcmp.eq.unc.s1 p7,p0         = FR_p_AbsX, FR_p_XN
                          // If arg is integer and negative - singularity branch
      nop.i         0
}
{ .mfi
(p10) add           GR_p_Offset    = 147, r0 // 1.25 < x < 1.75 table
      nop.f         0
(p11) add           GR_p_Offset    = 168, r0 // 1.75 < x < 2.0 table
};;

{ .mmf
      shladd        GR_p_Table     = GR_p_Offset, 4, GR_p_Table
      shladd        GR_p_Table2    = GR_p_Offset, 4, GR_p_Table2
      fma.s1        FR_r_XS        = FR_r_AbsX , f1, FR_r_XNS // xs = x - [x]
};;

{ .mmb
      ldfpd         FR_p_A5H, FR_p_A5L = [GR_p_Table], 16
      ldfpd         FR_p_A2H, FR_p_A2L = [GR_p_Table2], 16
(p7)  br.cond.spnt  tgammal_singularity // Singularity for integer /////////////
                                        // and negative argument ///////////////
};;

{ .mfi
      ldfpd         FR_p_A4H, FR_p_A4L = [GR_p_Table], 16
      fma.s1        FR_p_XN        = FR_p_XN, f1, FR_p_0p5 // xn = xn+0.5
      nop.i         0
}
{ .mfi
      ldfpd         FR_p_A1H, FR_p_A1L = [GR_p_Table2], 16
(p10) fms.s1        FR_p_XR        = FR_p_AbsX, f1, FR_p_1p5 // r = x - 1.5
      nop.i         0
};;

{ .mmi
      ldfpd         FR_p_A3H, FR_p_A3L = [GR_p_Table], 16
      ldfpd         FR_p_A0H, FR_p_A0L = [GR_p_Table2], 16
      nop.i         0
};;

{ .mmi
      ldfe         FR_p_A20        = [GR_p_Table], 16
      ldfe         FR_p_A12        = [GR_p_Table2], 16
      nop.i         0
};;

{ .mmf
      ldfe         FR_p_A19        = [GR_p_Table], 16
      ldfe         FR_p_A11        = [GR_p_Table2], 16
      fma.s1       FR_r_XS2        = FR_r_XS, FR_r_XS, f0 // xs2 = xs*xs
};;

{ .mmi
      ldfe          FR_p_A18       = [GR_p_Table], 16
      ldfe          FR_p_A10       = [GR_p_Table2], 16
      nop.i         0
};;

.pred.rel "mutex",p12,p13
{ .mfi
      ldfe          FR_p_A17       = [GR_p_Table], 16
(p12) fms.s1        FR_p_XR        = FR_p_AbsX, f1, FR_p_XN // r = x - xn
      nop.i         0
}
{ .mfi
      ldfe          FR_p_A9        = [GR_p_Table2], 16
(p13) fms.s1        FR_p_XR        = FR_p_AbsX, f1, FR_p_XN
      nop.i         0
};;

{ .mmi
      ldfe          FR_p_A16       = [GR_p_Table], 16
      ldfe          FR_p_A8        = [GR_p_Table2], 16
(p9)  cmp.eq        p12, p0        = r0, r0 // clear p12
};;

{ .mmi
      ldfe          FR_p_A15       = [GR_p_Table], 16
      ldfe          FR_p_A7        = [GR_p_Table2], 16
(p10) cmp.eq        p12, p0        = r0, r0 // clear p12
};;

{ .mfi
      ldfe          FR_p_A14       = [GR_p_Table], 16
      fma.s1        FR_r_TH        = FR_r_A2H, FR_r_XS2, f0 // sin for neg
(p11) cmp.eq        p12, p0        = r0, r0 // clear p12
}
{ .mfi
      ldfe          FR_p_A6        = [GR_p_Table2], 16
      fma.s1        FR_r_TL        = FR_r_A2L, FR_r_XS2, f0 // sin for neg
      nop.i         0
};;

{ .mfi
      ldfe          FR_p_A13       = [GR_p_Table], 16
      fms.s1        FR_r_XS2L      = FR_r_XS, FR_r_XS, FR_r_XS2 // x2Lo part
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp5H    = FR_p_A5H, FR_p_XR, f0 // A5H*r
                                                           // 'Low poly'
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR2       = FR_p_XR, FR_p_XR, f0 // r^2 = r*r
      nop.i         0
};;

{ .mfi
      nop.m         0
      fabs          FR_r_XS        = FR_r_XS // abs(xs)
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp2H    = FR_p_A2H, FR_p_XR, f0 // A2H*r
                                                           // 'High poly'
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_TT        = FR_r_A2H, FR_r_XS2, FR_r_TH // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ResH      = FR_r_TH, f1, FR_r_A1H // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_A2H, FR_r_XS2L, FR_r_TL // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp5L    = FR_p_A5H,FR_p_XR,FR_p_Temp5H //A5H*r delta
                                                                  // 'Low poly'
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly5H    = FR_p_Temp5H, f1, FR_p_A4H // A5H*r+A4H
                                                               // 'Low poly'
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp2L    = FR_p_A2H, FR_p_XR, FR_p_Temp2H//A2H*r delta
                                                                   //'High poly'
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly2H    = FR_p_Temp2H, f1, FR_p_A1H // A2H*r+A1H
                                                               //'High poly'
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_XR3       = FR_p_XR2, FR_p_XR,  f0 // r^3 = r^2*r
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_p_XR2L      = FR_p_XR, FR_p_XR, FR_p_XR2 // r^2 delta
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A18       = FR_p_A19, FR_p_XR, FR_p_A18 // Poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A14       = FR_p_A15, FR_p_XR, FR_p_A14 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_XR4       = FR_p_XR2, FR_p_XR2, f0 // r^4 = r^2*r^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp5L    = FR_p_A5L, FR_p_XR, FR_p_Temp5L// Low part
                                                                   // of A5*r+A4
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly5L    = FR_p_A4H, f1, FR_p_Poly5H // Low part
                                                               // of A5*r+A4
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp4H    = FR_p_Poly5H, FR_p_XR, f0 // (A5H*r+A4H)*r
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp2L    = FR_p_A2L, FR_p_XR, FR_p_Temp2L // A2*r low
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly2L    = FR_p_A1H, f1, FR_p_Poly2H // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1H    = FR_p_Poly2H, FR_p_XR, f0 // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_XR3L      = FR_p_XR2, FR_p_XR, FR_p_XR3 // x^3 delta
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A16       = FR_p_A17, FR_p_XR, FR_p_A16 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_ResL      = FR_r_A1H, f1, FR_r_ResH // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_TL, f1, FR_r_TT // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp5L    = FR_p_Temp5L, f1, FR_p_A4L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly5L    = FR_p_Poly5L, f1, FR_p_Temp5H // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp4L    = FR_p_Poly5H,FR_p_XR,FR_p_Temp4H //Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly4H    = FR_p_Temp4H, f1, FR_p_A3H // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp2L    = FR_p_Temp2L, f1, FR_p_A1L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly2L    = FR_p_Poly2L, f1, FR_p_Temp2H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp1L    = FR_p_Poly2H,FR_p_XR,FR_p_Temp1H //High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1H    = FR_p_Temp1H, f1, FR_p_A0H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A12       = FR_p_A13, FR_p_XR, FR_p_A12 // Poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR3L      = FR_p_XR2L, FR_p_XR, FR_p_XR3L // x^3 low
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly5L    = FR_p_Poly5L, f1, FR_p_Temp5L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A10       = FR_p_A11, FR_p_XR, FR_p_A10 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly4L    = FR_p_A3H, f1, FR_p_Poly4H // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A6        = FR_p_A7, FR_p_XR, FR_p_A6 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A8        = FR_p_A9, FR_p_XR, FR_p_A8 // Poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR6       = FR_p_XR4, FR_p_XR2, f0 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly2L    = FR_p_Poly2L, f1, FR_p_Temp2L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly1L    = FR_p_A0H, f1, FR_p_Poly1H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_ResL, f1, FR_r_TH // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TT        = FR_r_TL, f1, FR_r_A1L // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp4L    = FR_p_Poly5L,FR_p_XR,FR_p_Temp4L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A18       = FR_p_A20, FR_p_XR2, FR_p_A18 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly4L    = FR_p_Poly4L, f1, FR_p_Temp4H // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A14       = FR_p_A16, FR_p_XR2, FR_p_A14 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A6        = FR_p_A8, FR_p_XR2, FR_p_A6 // Poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A10       = FR_p_A12, FR_p_XR2, FR_p_A10 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1L    = FR_p_Poly2L,FR_p_XR,FR_p_Temp1L //High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1L    = FR_p_Poly1L, f1, FR_p_Temp1H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_ResL, f1, FR_r_TT // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TH        = FR_r_ResH, FR_r_XS2, f0 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp4L    = FR_p_Temp4L, f1, FR_p_A3L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3H    = FR_p_Poly4H, FR_p_XR3, f0 // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A14       = FR_p_A18, FR_p_XR4, FR_p_A14 // Poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR8       = FR_p_XR4, FR_p_XR4, f0 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_ResH, FR_r_XS2L, f0 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1L    = FR_p_Temp1L, f1, FR_p_A0L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A6        = FR_p_A10, FR_p_XR4, FR_p_A6 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_TT        = FR_r_ResH, FR_r_XS2, FR_r_TH // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_Res3H     = FR_r_TH, f1, f1 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly4L    = FR_p_Poly4L, f1, FR_p_Temp4L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3L    = FR_p_Poly4H, FR_p_XR3L, f0 // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly0H    = FR_p_Poly3H,f1,FR_p_Poly1H //Low & High add
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A7        = FR_r_A8,  FR_r_XS2, FR_r_A7 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_ResL, FR_r_XS2, FR_r_TL // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_XS4       = FR_r_XS2, FR_r_XS2, f0 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1L    = FR_p_Poly1L, f1, FR_p_Temp1L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_PolyTail  = FR_p_A14, FR_p_XR8, FR_p_A6 // Poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_Res3L     = f1, f1, FR_r_Res3H // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ResH      = FR_r_Res3H, FR_r_XS, f0 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp0L    = FR_p_Poly4H,FR_p_XR3,FR_p_Poly3H //Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3L    = FR_p_Poly4L,FR_p_XR3,FR_p_Poly3L //Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly0L    = FR_p_Poly1H,f1,FR_p_Poly0H //Low & High add
      nop.i         0
}
{ .mfi
      nop.m         0
(p13) fma.s1        FR_p_OddPoly0H = FR_p_Poly0H, FR_p_AbsXM1, f0
                                 // Reccurent computations - multiplying by X-1
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_TL, f1, FR_r_TT // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A3        = FR_r_A4,  FR_r_XS2, FR_r_A3 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1L    = FR_p_PolyTail,FR_p_XR6,FR_p_Poly1L//High
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A5        = FR_r_A6, FR_r_XS2, FR_r_A5 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res3L     = FR_r_Res3L, f1, FR_r_TH // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_r_ResL      = FR_r_Res3H, FR_r_XS, FR_r_ResH//sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3L    = FR_p_Poly3L, f1, FR_p_Temp0L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A7        = FR_r_A9, FR_r_XS4, FR_r_A7 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly0L    = FR_p_Poly0L,f1,FR_p_Poly3H //Low & High add
      nop.i         0
}
{ .mfi
      nop.m         0
(p13) fms.s1        FR_p_OddPoly0L = FR_p_Poly0H, FR_p_AbsXM1, FR_p_OddPoly0H
                       // Reccurent computations - multiplying by X-1 (low part)
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_A3        = FR_r_A5,  FR_r_XS4, FR_r_A3 // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_XS7       = FR_r_XS4, FR_r_XS2, f0 // xs^6
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res3L     = FR_r_Res3L, f1, FR_r_TL // sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_XS8       = FR_r_XS4, FR_r_XS4, f0 // sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp0H    = FR_p_Poly3L,f1,FR_p_Poly1L //Low & High add
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_XS7       = FR_r_XS7, FR_r_XS,  f0 // xs^7
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_Res3L, FR_r_XS, FR_r_ResL//sin for neg
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_Tail      = FR_r_A7, FR_r_XS8, FR_r_A3 // sin tail res
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly0L    = FR_p_Poly0L,f1,FR_p_Temp0H //Low & High add
      nop.i         0
};;


{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_Tail,FR_r_XS7,FR_r_ResL //sin for neg
      nop.i         0
};;

{ .mfi
      nop.m         0
(p13) fma.s1        FR_p_OddPoly0L  = FR_p_Poly0L, FR_p_AbsXM1, FR_p_OddPoly0L
                       // Reccurent computations - multiplying by X-1 (low part)
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TT        = FR_r_ResL, FR_r_AbsX, f0 // X*sin
      nop.i         0
};;

.pred.rel "mutex",p12,p13
{ .mfi
      nop.m         0
(p12) fma.s0        f8             =   FR_p_Poly0H, f1, FR_p_Poly0L // Even
      nop.i         0
}
{ .mfb
      nop.m         0
(p13) fma.s0        f8             =   FR_p_OddPoly0H, f1, FR_p_OddPoly0L // Odd
(p14) br.ret.spnt   b0  // Exit for 1 <= |X| < 13 path (positive arguments)/////
};;

{ .mfi
      nop.m         0
(p13) fma.s1        FR_p_Poly0H    = FR_p_OddPoly0H, f1, f0
                                                       // Reccurent computations
      nop.i         0
}
{ .mfi
      nop.m         0
(p13) fma.s1        FR_p_Poly0L    = FR_p_OddPoly0L, f1, f0
                                                       // Reccurent computations
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res1H     = FR_r_ResH, FR_r_AbsX, FR_r_TT // X*sin
(p11) cmp.eq        p13, p12       = r0, r0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_Res1L     = FR_r_ResH,FR_r_AbsX,FR_r_Res1H// X*sin
(p9)  cmp.eq        p13, p12       = r0, r0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res1L     = FR_r_Res1L, f1, FR_r_TT // sin for neg
(p10) cmp.eq        p13, p12       = r0, r0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_p_Poly0L, FR_r_Res1H, f0 // mult by sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_p_Poly0H,FR_r_Res1L,FR_r_TL//mult by sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResH      = FR_p_Poly0H,FR_r_Res1H,FR_r_TL//mult by sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_ResL      = FR_p_Poly0H,FR_r_Res1H,FR_r_ResH//sin mult
      nop.i         0
};;

{ .mfi
      nop.m         0
      frcpa.s1      FR_r_Y0,p0     = f1,FR_r_ResH //  y = frcpa(b)
      nop.i         0
};;

{ .mfi
      nop.m         0
      fneg          FR_r_NegOne    = f1 // Form -1.0
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_ResL, f1, FR_r_TL //Low result of mult
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Q0        = f1,FR_r_Y0,f0 //  q = a*y
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_r_E0        = FR_r_Y0,FR_r_ResH,f1 //  e = 1-b*y
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_E2        = FR_r_E0,FR_r_E0,FR_r_E0 //  e2 = e+e^2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_E1        = FR_r_E0,FR_r_E0,f0 //  e1 = e^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Y1        = FR_r_Y0,FR_r_E2,FR_r_Y0 //  y1 = y+y*e2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_E3        = FR_r_E1,FR_r_E1,FR_r_E0 //  e3 = e+e1^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Y2        = FR_r_Y1,FR_r_E3,FR_r_Y0 //  y2 = y+y1*e3
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_r_R0        = FR_r_ResH,FR_r_Q0,f1 //  r = a-b*q
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_r_E4        = FR_r_ResH,FR_r_Y2,f1 //  e4 = 1-b*y2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ZH        = FR_r_R0,FR_r_Y2,FR_r_Q0 //  x = q+r*y2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Y3        = FR_r_Y2,FR_r_E4,FR_r_Y2 //  y3 = y2+y2*e4
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_r_R1        = FR_r_ResH,FR_r_ZH,f1 //  r1 = a-b*x
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_r_R1        = FR_r_ResL,FR_r_ZH,FR_r_R1 // r1=r1-b_lo*X
      nop.i         0
}
{ .mfi
      nop.m         0
(p12) fma.s1        FR_r_ZHN       = FR_r_ZH,FR_r_NegOne, f0 // Negate for evens
      nop.i         0
};;

.pred.rel "mutex",p13,p12
{ .mfi
      nop.m         0
(p13) fma.s0        f8             = FR_r_R1,FR_r_Y3,FR_r_ZH // Final result
      nop.i         0
}
{ .mfb
      nop.m         0
(p12) fnma.s0       f8             = FR_r_R1,FR_r_Y3,FR_r_ZHN // Final result
      br.ret.sptk   b0 // Exit for 1 <= |X| < 13 path (negative arguments)//////
};;


////////////  |X| < 1 path /////////////////////////////////////////////////////
//------------------------------------------------------------------------------
.align 64
tgamma_lt_1:
{ .mfi
      getf.exp      GR_p_Exp       = FR_p_AbsX // exp of abs X
      fma.s1        FR_z_Q0        = f1,FR_z_Y0,f0 // q = a*y
      add           GR_r_sin_Table2= 0x50, GR_r_sin_Table
}
{ .mfi
      ldfpd         FR_p_0p5, FR_p_1p5 = [GR_c_Table], 16
      fnma.s1       FR_z_E0        = FR_z_Y0,f8,f1 //  e = 1-b*y
      add           GR_p_Table2    = 0xB0, GR_p_Table
};;

{ .mfi
      ldfd          FR_p_0p25      = [GR_c_Table]
      fcvt.xf       FR_r_XNS       = FR_r_IXNS // Convert int repr to float
      shr.u         GR_p_X_Sgnd    = GR_p_X_Sgnd, 60
                                       // Obtain only 4 bits of significand
}
{ .mfi
      nop.m        0
      nop.f        0
      add          GR_p_Bias           = 0xffff, r0 // Set bias
};;

{ .mfi
      ldfpd        FR_r_A2H, FR_r_A2L  = [GR_r_sin_Table], 16
      nop.f        0
      shl          GR_p_XN             = GR_p_Exp, 4
                       // Shift exp to 4 bits left to set place for significand
}
{ .mlx
      ldfe         FR_r_A6         = [GR_r_sin_Table2], 16
      movl         GR_p_0p75       = 0xfffec // 0.75
};;

{ .mfi
      ldfpd        FR_r_A1H, FR_r_A1L = [GR_r_sin_Table], 16
      nop.f        0
      or           GR_p_XN         = GR_p_XN, GR_p_X_Sgnd
                                 // Combine exp with 4 high bits of significand
}
{ .mfi
      ldfe         FR_r_A5         = [GR_r_sin_Table2], 16
      nop.f        0
      sub          GR_p_Exp        = GR_p_Exp, GR_p_Bias // Unbiased exp
};;

{ .mmi
      ldfe         FR_r_A9         = [GR_r_sin_Table], 16
      ldfe         FR_r_A4         = [GR_r_sin_Table2], 16
      cmp.gtu.unc  p10, p11        = GR_p_0p75, GR_p_XN // sgnd(x) < 0.75
};;

{ .mfi
      ldfe          FR_r_A8        = [GR_r_sin_Table], 16
      fma.s1        FR_z_E2        = FR_z_E0,FR_z_E0,FR_z_E0 //  e2 = e+e^2
(p10) cmp.gt.unc    p9, p10        = -2, GR_p_Exp //  x < 0.25
}
{ .mfi
      ldfe          FR_r_A3        = [GR_r_sin_Table2], 16
      fma.s1        FR_z_E1        = FR_z_E0,FR_z_E0,f0 // e1 = e^2
(p11) add           GR_p_Offset    = 168, r0 // [0.75;1] interval
};;

{ .mmi
(p10) add           GR_p_Offset    = 147, r0 // [0.25;0.75] interval
      ldfe          FR_r_A7        = [GR_r_sin_Table], 16
(p9)  cmp.gt.unc    p8, p9         = -3, GR_p_Exp // x < 0.125
};;

.pred.rel "mutex",p9,p8
{ .mmi
(p9)  add           GR_p_Offset    = 126, r0 // [0.125;0.25] interval
(p8)  add           GR_p_Offset    = 189, r0 // [0.;0.125] interval
      nop.i         0
};;

{ .mmf
      shladd        GR_p_Table     = GR_p_Offset, 4, GR_p_Table //Make addresses
      shladd        GR_p_Table2    = GR_p_Offset, 4, GR_p_Table2
      fma.s1        FR_r_XS        = FR_r_AbsX , f1, FR_r_XNS // xs = |x|-[x]
};;

.pred.rel "mutex",p8,p11
{ .mfi
      ldfpd         FR_p_A5H, FR_p_A5L = [GR_p_Table], 16
(p11) fms.s1        FR_p_XR            = f1, f1, FR_p_AbsX // r = 1 - |x|
                                                 // for [0.75;1] interval
      nop.i         0
}
{ .mfi
      ldfpd        FR_p_A2H, FR_p_A2L = [GR_p_Table2], 16
(p8)  fms.s1       FR_p_XR            = FR_p_AbsX, f1, f0 // r = |x|
                                                      // for [0.;0.125] interval
      nop.i         0
};;

{ .mfi
      ldfpd         FR_p_A4H, FR_p_A4L = [GR_p_Table], 16
      fma.s1        FR_z_Y1        = FR_z_Y0,FR_z_E2,FR_z_Y0 // y1 = y+y*e2
      nop.i         0
}
{ .mfi
      ldfpd         FR_p_A1H, FR_p_A1L = [GR_p_Table2], 16
      fma.s1        FR_z_E3        = FR_z_E1,FR_z_E1,FR_z_E0 // e3 = e+e1^2
      nop.i         0
};;

.pred.rel "mutex",p9,p10
{ .mfi
      ldfpd         FR_p_A3H, FR_p_A3L = [GR_p_Table], 16
(p9)  fms.s1        FR_p_XR        = FR_p_AbsX, f1, f0 // r = |x|
                                                  // for [0.125;0.25] interval
      nop.i         0
}
{ .mfi
      ldfpd         FR_p_A0H, FR_p_A0L  = [GR_p_Table2], 16
(p10) fms.s1        FR_p_XR        = FR_p_AbsX, f1, FR_p_0p5 // r = |x| - 0.5
                                                 // for [0.25;0.75] interval
      nop.i         0
};;

{ .mmi
      ldfe          FR_p_A20       = [GR_p_Table], 16
      ldfe          FR_p_A12       = [GR_p_Table2], 16
      nop.i         0
};;

{ .mfi
      ldfe          FR_p_A19       = [GR_p_Table], 16
      fma.s1        FR_r_XS2       = FR_r_XS, FR_r_XS, f0 // xs^2
      nop.i         0
}
{ .mfi
      ldfe          FR_p_A11       = [GR_p_Table2], 16
      nop.f         0
      nop.i         0
};;

{ .mmi
      ldfe          FR_p_A18       = [GR_p_Table], 16
      ldfe          FR_p_A10       = [GR_p_Table2], 16
      nop.i         0
};;

.pred.rel "mutex",p12,p13
{ .mfi
      ldfe          FR_p_A17       = [GR_p_Table], 16
      fma.s1        FR_z_Y2        = FR_z_Y1,FR_z_E3,FR_z_Y0 // y2 = y+y1*e3
      nop.i         0
}
{ .mfi
      ldfe          FR_p_A9        = [GR_p_Table2], 16
      fnma.s1       FR_z_R0        = f8,FR_z_Q0,f1 //  r = a-b*q
      nop.i         0
};;

{ .mmi
      ldfe          FR_p_A16       = [GR_p_Table], 16
      ldfe          FR_p_A8        = [GR_p_Table2], 16
      nop.i         0
};;

{ .mmi
      ldfe          FR_p_A15       = [GR_p_Table], 16
      ldfe          FR_p_A7        = [GR_p_Table2], 16
      nop.i         0
};;

{ .mfi
      ldfe          FR_p_A14       = [GR_p_Table], 16
      fma.s1        FR_r_TH        = FR_r_A2H, FR_r_XS2, f0 // neg sin
      nop.i         0
}
{ .mfi
      ldfe          FR_p_A6        = [GR_p_Table2], 16
      fma.s1        FR_r_TL        =   FR_r_A2L, FR_r_XS2, f0 // neg sin
      nop.i         0
};;

{ .mfi
      ldfe          FR_p_A13       = [GR_p_Table], 16
      fms.s1        FR_r_XS2L      = FR_r_XS, FR_r_XS, FR_r_XS2 // xs^2 delta
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp5H     = FR_p_A5H, FR_p_XR, f0 // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR2       = FR_p_XR, FR_p_XR, f0 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fabs          FR_r_XS        = FR_r_XS // Absolute value of xs
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp2H    = FR_p_A2H, FR_p_XR, f0 // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_z_E4        = f8,FR_z_Y2,f1 //  e4 = 1-b*y2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_z_ZH        = FR_z_R0,FR_z_Y2,FR_z_Q0 // 1/x = q+r*y2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_TT        = FR_r_A2H, FR_r_XS2, FR_r_TH // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ResH      = FR_r_TH, f1, FR_r_A1H // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_A2H, FR_r_XS2L, FR_r_TL // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp5L    = FR_p_A5H, FR_p_XR, FR_p_Temp5H // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly5H    = FR_p_Temp5H, f1, FR_p_A4H // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp2L    = FR_p_A2H, FR_p_XR, FR_p_Temp2H // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly2H    = FR_p_Temp2H, f1, FR_p_A1H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_XR3       = FR_p_XR2, FR_p_XR,  f0 // r^3
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_p_XR2L      = FR_p_XR, FR_p_XR, FR_p_XR2 // r^2 delta
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A18       = FR_p_A19, FR_p_XR, FR_p_A18 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A14       = FR_p_A15, FR_p_XR, FR_p_A14 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_XR4       = FR_p_XR2, FR_p_XR2, f0 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_z_Y3        = FR_z_Y2,FR_z_E4,FR_z_Y2 //  y3 = y2+y2*e4
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp5L    = FR_p_A5L, FR_p_XR, FR_p_Temp5L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly5L    = FR_p_A4H, f1, FR_p_Poly5H // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp4H    = FR_p_Poly5H, FR_p_XR, f0 // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp2L    = FR_p_A2L, FR_p_XR, FR_p_Temp2L // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly2L    = FR_p_A1H, f1, FR_p_Poly2H // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1H    = FR_p_Poly2H, FR_p_XR, f0 // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_XR3L      = FR_p_XR2, FR_p_XR, FR_p_XR3 // x^3 delta
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A16       = FR_p_A17, FR_p_XR, FR_p_A16 //poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_ResL      = FR_r_A1H, f1, FR_r_ResH // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_TL, f1, FR_r_TT // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp5L    = FR_p_Temp5L, f1, FR_p_A4L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly5L    = FR_p_Poly5L, f1, FR_p_Temp5H //Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp4L    = FR_p_Poly5H, FR_p_XR, FR_p_Temp4H//Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly4H    = FR_p_Temp4H, f1, FR_p_A3H // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp2L    = FR_p_Temp2L, f1, FR_p_A1L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly2L    = FR_p_Poly2L, f1, FR_p_Temp2H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp1L    = FR_p_Poly2H,FR_p_XR,FR_p_Temp1H //High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1H    = FR_p_Temp1H, f1, FR_p_A0H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A12       = FR_p_A13, FR_p_XR, FR_p_A12 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR3L      = FR_p_XR2L, FR_p_XR, FR_p_XR3L // x^3 low
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly5L    = FR_p_Poly5L, f1, FR_p_Temp5L //Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A10       = FR_p_A11, FR_p_XR, FR_p_A10 //poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly4L    = FR_p_A3H, f1, FR_p_Poly4H /// Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A6        = FR_p_A7, FR_p_XR, FR_p_A6 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A8        = FR_p_A9, FR_p_XR, FR_p_A8 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR6       = FR_p_XR4, FR_p_XR2, f0 // r^6
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly2L    = FR_p_Poly2L, f1, FR_p_Temp2L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly1L    = FR_p_A0H, f1, FR_p_Poly1H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_ResL, f1, FR_r_TH // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TT        = FR_r_TL, f1, FR_r_A1L // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp4L    = FR_p_Poly5L,FR_p_XR,FR_p_Temp4L //Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A18       = FR_p_A20, FR_p_XR2, FR_p_A18 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly4L    = FR_p_Poly4L, f1, FR_p_Temp4H // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A14       = FR_p_A16, FR_p_XR2, FR_p_A14 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A6        = FR_p_A8, FR_p_XR2, FR_p_A6 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A10       = FR_p_A12, FR_p_XR2, FR_p_A10 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1L    = FR_p_Poly2L,FR_p_XR,FR_p_Temp1L //High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1L    = FR_p_Poly1L, f1, FR_p_Temp1H // High poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_ResL, f1, FR_r_TT // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TH        = FR_r_ResH, FR_r_XS2, f0 // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp4L    = FR_p_Temp4L, f1, FR_p_A3L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3H    = FR_p_Poly4H, FR_p_XR3, f0 // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_A14       = FR_p_A18, FR_p_XR4, FR_p_A14 // poly tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_XR8       = FR_p_XR4, FR_p_XR4, f0 // r^8
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_ResH, FR_r_XS2L, f0 // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_z_R1        = f8,FR_z_ZH,f1 //  r1 = a-b*x
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1L    = FR_p_Temp1L, f1, FR_p_A0L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_A6        = FR_p_A10, FR_p_XR4, FR_p_A6 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_TT        = FR_r_ResH, FR_r_XS2, FR_r_TH // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_Res3H     = FR_r_TH, f1, f1 // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly4L    = FR_p_Poly4L, f1, FR_p_Temp4L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3L    = FR_p_Poly4H, FR_p_XR3L, f0 // Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly0H    = FR_p_Poly3H, f1, FR_p_Poly1H // Result
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A7        = FR_r_A8, FR_r_XS2, FR_r_A7 // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_ResL, FR_r_XS2, FR_r_TL // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_XS4       = FR_r_XS2, FR_r_XS2, f0 // xs^4
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1L    = FR_p_Poly1L, f1, FR_p_Temp1L // High poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_PolyTail  = FR_p_A14, FR_p_XR8, FR_p_A6 // poly tail
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_Res3L     = f1, f1, FR_r_Res3H // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ResH      = FR_r_Res3H, FR_r_XS, f0 // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Temp0L    = FR_p_Poly4H,FR_p_XR3,FR_p_Poly3H //Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3L    = FR_p_Poly4L,FR_p_XR3,FR_p_Poly3L //Low poly
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_p_Poly0L    = FR_p_Poly1H, f1, FR_p_Poly0H // Result
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_z_ZL        = FR_z_R1,FR_z_Y3, f0 //  x_lo = r1*y3
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_r_TL, f1, FR_r_TT // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A3        = FR_r_A4, FR_r_XS2, FR_r_A3 /// neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly1L    = FR_p_PolyTail,FR_p_XR6,FR_p_Poly1L // High
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A5        = FR_r_A6, FR_r_XS2, FR_r_A5 // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res3L     = FR_r_Res3L, f1, FR_r_TH // neg sin
      nop.i         0
}
{ .mfi
      nop.m         0
      fms.s1        FR_r_ResL      = FR_r_Res3H, FR_r_XS, FR_r_ResH // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly3L    = FR_p_Poly3L, f1, FR_p_Temp0L // Low poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_A7        = FR_r_A9,  FR_r_XS4, FR_r_A7 // neg sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly0L    = FR_p_Poly0L, f1, FR_p_Poly3H // result
      nop.i         0
};;

{ .mfi
      nop.m         0
(p14) fma.s1        f8             = FR_p_Poly0H, FR_z_ZH, f0 // z*poly
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp1L    = FR_p_Poly0H, FR_z_ZL, f0 // z*poly low
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_A3        = FR_r_A5, FR_r_XS4, FR_r_A3 // sin tail
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_XS7       = FR_r_XS4, FR_r_XS2, f0  // xs^6
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res3L     = FR_r_Res3L, f1, FR_r_TL // sin low
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_XS8       = FR_r_XS4, FR_r_XS4, f0 // xs^8
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Temp0H    = FR_p_Poly3L, f1, FR_p_Poly1L // result
      nop.i         0
};;

{ .mfi
      nop.m         0
(p14) fms.s1        FR_p_Temp1H    = FR_p_Poly0H, FR_z_ZH, f8 // hi result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_XS7       = FR_r_XS7, FR_r_XS,  f0 // xs^7
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_Res3L, FR_r_XS, FR_r_ResL // lo result
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_Tail      = FR_r_A7, FR_r_XS8, FR_r_A3 // tail result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_p_Poly0L    = FR_p_Poly0L, f1, FR_p_Temp0H // lo result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_Tail, FR_r_XS7, FR_r_ResL // lo result
      nop.i         0
};;

{ .mfi
      nop.m         0
(p14) fma.s1        FR_p_Temp1L    = FR_p_Poly0L,FR_z_ZH,FR_p_Temp1L //hi result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TT        = FR_r_ResL, f1, f0 // for low result
      nop.i         0
};;

.pred.rel "mutex",p12,p13
{ .mfi
      nop.m         0
(p14) fma.s1        FR_p_Temp1L    = FR_p_Temp1L, f1, FR_p_Temp1H // for lo res
      nop.i         0
};;

{ .mfi
(p10) cmp.eq        p13, p12       = r0, r0 // set p13, clear p12
      fma.s1        FR_r_Res1H     = FR_r_ResH, f1, FR_r_TT // hi res
      nop.i         0
};;

{ .mfb
(p9)  cmp.eq        p13, p12       = r0, r0 // set p13, clear p12
(p14) fma.s0        f8             =   f8, f1, FR_p_Temp1L // Final result
(p14) br.ret.spnt   b0 // Exit for  0 < |X| < 1 path (positive arguments)///////
};;

{ .mfi
(p11) cmp.eq        p13, p12       = r0, r0 // set p13, clear p12
      fms.s1        FR_r_Res1L     = FR_r_ResH, f1, FR_r_Res1H // Low sin result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Res1L     = FR_r_Res1L, f1, FR_r_TT // Low sin result
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_p_Poly0L,FR_r_Res1H,f0 //Low sin result
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_TL        = FR_p_Poly0H, FR_r_Res1L, FR_r_TL //Low sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_ResH      = FR_p_Poly0H, FR_r_Res1H, FR_r_TL //High sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fms.s1        FR_r_ResL      = FR_p_Poly0H,FR_r_Res1H,FR_r_ResH //Low res
      nop.i         0
};;

{ .mfi
      nop.m         0
      frcpa.s1      FR_r_Y0,p0     = f1,FR_r_ResH //  y = frcpa(b)
      nop.i         0
};;

{ .mfi
      nop.m         0
      fneg          FR_r_NegOne    = f1 // Construct -1.0
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ResL      = FR_r_ResL, f1, FR_r_TL // low sin
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Q0        = f1,FR_r_Y0,f0 // q = a*y
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_r_E0        = FR_r_Y0,FR_r_ResH,f1 // e = 1-b*y
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_E2        = FR_r_E0,FR_r_E0,FR_r_E0 // e2 = e+e^2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_E1        = FR_r_E0,FR_r_E0,f0 // e1 = e^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Y1        = FR_r_Y0,FR_r_E2,FR_r_Y0 //  y1 = y+y*e2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_E3        = FR_r_E1,FR_r_E1,FR_r_E0 //  e3 = e+e1^2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Y2        = FR_r_Y1,FR_r_E3,FR_r_Y0 //  y2 = y+y1*e3
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_r_R0        = FR_r_ResH,FR_r_Q0,f1 //  r = a-b*q
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_r_E4        = FR_r_ResH,FR_r_Y2,f1 //  e4 = 1-b*y2
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ZH        = FR_r_R0,FR_r_Y2,FR_r_Q0 //  x = q+r*y2
      nop.i         0
};;

{ .mfi
      nop.m         0
      fma.s1        FR_r_Y3        = FR_r_Y2,FR_r_E4,FR_r_Y2 //  y3 = y2+y2*e4
      nop.i         0
}
{ .mfi
      nop.m         0
      fnma.s1       FR_r_R1        = FR_r_ResH,FR_r_ZH,f1 //  r1 = a-b*x
      nop.i         0
};;

{ .mfi
      nop.m         0
      fnma.s1       FR_r_R1        = FR_r_ResL,FR_r_ZH,FR_r_R1 // r1=r1 - b_lo*X
      nop.i         0
}
{ .mfi
      nop.m         0
      fma.s1        FR_r_ZHN       = FR_r_ZH,FR_r_NegOne, f0 // Negate
      nop.i         0
};;

.pred.rel "mutex",p13,p12
{ .mfb
      nop.m         0
      fnma.s0       f8             = FR_r_R1,FR_r_Y3,FR_r_ZHN // Result for neg
      br.ret.sptk   b0  // Exit for  0 < |X| < 1 path (negative arguments)//////
};;




//  SPECIALS (x for natval, nan, +/-inf or +/-0) ///////////////////////////////
//------------------------------------------------------------------------------
.align 32
tgammal_spec:
{ .mlx
      nop.m         0
      movl          GR_DenOverflow = 0x2000000000000001
}
{ .mfi
      nop.m         0
      fclass.m      p9,p0          =  f8,0xB // +/-denormals
      nop.i         0
};;
{ .mfi
      nop.m         0
      fclass.m      p6,p0          =  f8,0x1E1 // Test x for natval, nan, +inf
      nop.i         0
};;
{ .mfi
      nop.m         0
      fclass.m      p7,p8          = f8,0x7 // +/-0
      nop.i         0
}

{ .mfi
(p9)  cmp.ltu.unc   p10,p11        = GR_l_signif_Z, GR_DenOverflow
(p9)  fnorm.s0      f8 = f8
      nop.i         0
};;

{ .mfb
      nop.m         0
(p9)  fcvt.fx.trunc.s1 FR_n_IXN    = FR_l_AbsX // Round by truncate
(p11) br.cond.sptk  tgamma_lt_1 // Return to gamma ('good' denormal)////////////
};;

{ .mfb
      nop.m         0
      nop.f         0
(p10) br.cond.spnt  tgammal_overflow // "Bad" denormal - overflow! /////////////
};;

{ .mfi
      nop.m         0
      mov           FR_X           = f8 // for error handler
      nop.i         0
}
{ .mfb
      nop.m         0
(p6)  fma.s0        f8             = f8,f1,f8 // res = x + x
(p6)  br.ret.spnt   b0 // Exit for NAN, INF and NatVals ////////////////////////
};;
.pred.rel "mutex",p7,p8
{ .mfi
(p7)  mov           GR_Parameter_TAG = 256   // negative
(p7)  frcpa.s0      f8,p0            = f1,f8 // Raise V flag
      nop.i         0
}
{ .mfb
      nop.m         0
      nop.f         0
(p8)  br.cond.spnt  tgammal_singularity // Branch for +ZERO ////////////////////
};;

{ .mfb
      nop.m         0
      nop.f         0
      br.cond.spnt  tgammal_libm_err // Branch for -ZERO ///////////////////////
};;




// SINGULARITY (x is negative integer or 0) ////////////////////////////////////
//------------------------------------------------------------------------------
.align 32
tgammal_singularity:
{ .mfi
      nop.m         0
      mov           FR_X             = f8  // For error handler
      mov           GR_Parameter_TAG = 256 // negative
}
{ .mfb
      nop.m         0
      frcpa.s0      f8,p0 = f0,f0 // Raise V flag
      br.cond.sptk  tgammal_libm_err // Call error handler /////////////////////
                                     // with singularity error /////////////////
};;




// OVERFLOW (result is too big and cannot be represented by normal value) //////
// ( X > 1755.54 and for denormals with abs value less than 0x2000000000000001 )
//------------------------------------------------------------------------------
.align 32
tgammal_overflow:
{ .mfi
      addl          r8             = 0x1FFFE, r0 // Exp of INF
      fcmp.lt.s1    p15,p14        = f8,f0 // p14 - pos arg, p15 - neg arg
      nop.i         0
};;

{ .mfi
      setf.exp      f9               = r8
      mov           FR_X             = f8 // For error handler
      mov           GR_Parameter_TAG = 255 // overflow
};;

.pred.rel "mutex",p14,p15
{ .mfi
      nop.m         0
(p14) fma.s0        f8             = f9,f9,f0 // Set I,O and +INF result
      nop.i         0
}
{ .mfb
      nop.m         0
(p15) fnma.s0       f8             = f9,f9,f0 // Set I,O and -INF result
      br.cond.sptk  tgammal_libm_err // Call error handler /////////////////////
                                     // with overflow error ////////////////////
};;





// UNDERFLOW (x is negative noninteger with big absolute value) ////////////////
//------------------------------------------------------------------------------
.align 32
tgammal_underflow:
{ .mfi
      nop.m         0
      fcvt.fx.trunc.s1 FR_u_IXN    = f8 // Convert arg to int repres. in FR
      nop.i         0
};;

{ .mmi
      getf.sig      GR_u_XN        = FR_u_IXN
      mov           r11            = 0x00001
      nop.i         0
};;

{ .mfi
      setf.exp      f9             = r11
      nop.f         0
      nop.i         0
};;

{ .mfi
      nop.m         0
      nop.f         0
      tbit.z        p6,p7          = GR_u_XN,0 // even or odd
};;

.pred.rel "mutex",p6,p7
{ .mfi
      nop.m         0
(p6)  fms.s0        f8             = f9,f9,f9 // for negatives
      nop.i         0
}
{ .mfb
      nop.m         0
(p7)  fma.s0        f8             = f9,f9,f9 // for positives
      br.ret.sptk   b0 // Exit for underflow path //////////////////////////////
};;


GLOBAL_LIBM_END(tgammal)




////////////////// Tgammal error handler ///////////////////////////////////////
//------------------------------------------------------------------------------
LOCAL_LIBM_ENTRY(__libm_error_region)
tgammal_libm_err:
.prologue
{ .mfi
        add   GR_Parameter_Y=-32,sp             // Parameter 2 value
        nop.f 0
.save   ar.pfs,GR_SAVE_PFS
        mov  GR_SAVE_PFS=ar.pfs                 // Save ar.pfs
}
{ .mfi
.fframe 64
        add sp=-64,sp                           // Create new stack
        nop.f 0
        mov GR_SAVE_GP=gp                       // Save gp
};;
{ .mmi
        stfe [GR_Parameter_Y] = FR_Y,16         // Save Parameter 2 on stack
        add GR_Parameter_X = 16,sp              // Parameter 1 address
.save   b0, GR_SAVE_B0
        mov GR_SAVE_B0=b0                       // Save b0
};;
.body
{ .mib
        stfe [GR_Parameter_X] = FR_X            // Store Parameter 1 on stack
        add   GR_Parameter_RESULT = 0,GR_Parameter_Y
        nop.b 0                                 // Parameter 3 address
}
{ .mib
        stfe [GR_Parameter_Y] = FR_RESULT      // Store Parameter 3 on stack
        add   GR_Parameter_Y = -16,GR_Parameter_Y
        br.call.sptk b0=__libm_error_support#  // Call error handling function
};;
{ .mmi
        nop.m 999
        nop.m 999
        add   GR_Parameter_RESULT = 48,sp
};;
{ .mmi
        ldfe  f8 = [GR_Parameter_RESULT]       // Get return result off stack
.restore sp
        add   sp = 64,sp                       // Restore stack pointer
        mov   b0 = GR_SAVE_B0                  // Restore return address
};;
{ .mib
        mov   gp = GR_SAVE_GP                  // Restore gp
        mov   ar.pfs = GR_SAVE_PFS             // Restore ar.pfs
        br.ret.sptk     b0                     // Return
};;

LOCAL_LIBM_END(__libm_error_region#)

.type   __libm_error_support#,@function
.global __libm_error_support#
