diff options
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/lib/support/primitives.c')
-rw-r--r-- | Build/source/texk/web2c/mfluadir/otfcc/lib/support/primitives.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/lib/support/primitives.c b/Build/source/texk/web2c/mfluadir/otfcc/lib/support/primitives.c new file mode 100644 index 00000000000..2f2ad360979 --- /dev/null +++ b/Build/source/texk/web2c/mfluadir/otfcc/lib/support/primitives.c @@ -0,0 +1,66 @@ +#include "otfcc/primitives.h" +#include "bin-io.h" +#include <math.h> + +// f2dot14 type +double otfcc_from_f2dot14(const f2dot14 x) { + return x / 16384.0; +} +int16_t otfcc_to_f2dot14(const double x) { + return round(x * 16384.0); +} + +// F16.16 (fixed) type +double otfcc_from_fixed(const f16dot16 x) { + return x / 65536.0; +} +f16dot16 otfcc_to_fixed(const double x) { + return round(x * 65536.0); +} + +// F16.16 arith +// Clamp: remove too-large values +static INLINE f16dot16 clamp(int64_t value) { + int64_t tmp = value; + if (tmp < (int64_t)f16dot16_negativeIntinity) tmp = (int64_t)f16dot16_negativeIntinity; + if (tmp > (int64_t)f16dot16_infinity) tmp = (int64_t)f16dot16_infinity; + return (f16dot16)tmp; +} + +f16dot16 otfcc_f1616_add(f16dot16 a, f16dot16 b) { + return a + b; +} +f16dot16 otfcc_f1616_minus(f16dot16 a, f16dot16 b) { + return a - b; +} + +f16dot16 otfcc_f1616_multiply(f16dot16 a, f16dot16 b) { + int64_t tmp = (int64_t)a * (int64_t)b + f16dot16_k; + f16dot16 product = clamp(tmp >> f16dot16_precision); + return product; +} + +static INLINE f16dot16 divide(int64_t a, int32_t b) { + if (b == 0) { + if (a < 0) + return f16dot16_negativeIntinity; + else + return f16dot16_infinity; + } + + if ((a < 0 != b < 0)) { + a -= b / 2; + } else { + a += b / 2; + } + + return (f16dot16)(clamp(a / b)); +} + +f16dot16 otfcc_f1616_muldiv(f16dot16 a, f16dot16 b, f16dot16 c) { + int64_t tmp = (int64_t)a * (int64_t)b + f16dot16_k; + return divide(tmp, c); +} +f16dot16 otfcc_f1616_divide(f16dot16 a, f16dot16 b) { + return divide((int64_t)a << f16dot16_precision, b); +} |