1//========================================================================
2//
3// SplashMath.h
4//
5//========================================================================
6
7//========================================================================
8//
9// Modified under the Poppler project - http://poppler.freedesktop.org
10//
11// All changes made under the Poppler project to this file are licensed
12// under GPL version 2 or later
13//
14// Copyright (C) 2009-2011 Albert Astals Cid <aacid@kde.org>
15// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
16// Copyright (C) 2020 Jean Ghali <jghali@libertysurf.fr>
17//
18// To see a description of the changes please see the Changelog file that
19// came with your tarball or type make ChangeLog if you are building from git
20//
21//========================================================================
22
23#ifndef SPLASHMATH_H
24#define SPLASHMATH_H
25
26#include "poppler-config.h"
27
28#include <cmath>
29#include "SplashTypes.h"
30
31static inline SplashCoord splashAbs(SplashCoord x)
32{
33#if defined(USE_FLOAT)
34 return fabsf(x);
35#else
36 return fabs(x: x);
37#endif
38}
39
40static inline int splashFloor(SplashCoord x)
41{
42#if defined(USE_FLOAT)
43 return (int)floorf(x);
44#elif defined(__GNUC__) && defined(__i386__)
45 // floor() and (int)() are implemented separately, which results
46 // in changing the FPCW multiple times - so we optimize it with
47 // some inline assembly
48 unsigned short oldCW, newCW, t;
49 int result;
50
51 __asm__ volatile("fldl %4\n"
52 "fnstcw %0\n"
53 "movw %0, %3\n"
54 "andw $0xf3ff, %3\n"
55 "orw $0x0400, %3\n"
56 "movw %3, %1\n" // round down
57 "fldcw %1\n"
58 "fistpl %2\n"
59 "fldcw %0\n"
60 : "=m"(oldCW), "=m"(newCW), "=m"(result), "=r"(t)
61 : "m"(x));
62 return result;
63#elif defined(_WIN32) && defined(_M_IX86)
64 // floor() and (int)() are implemented separately, which results
65 // in changing the FPCW multiple times - so we optimize it with
66 // some inline assembly
67 unsigned short oldCW, newCW;
68 int result;
69
70 __asm fld QWORD PTR x;
71 __asm fnstcw WORD PTR oldCW;
72 __asm mov ax, WORD PTR oldCW;
73 __asm and ax, 0xf3ff;
74 __asm or ax, 0x0400;
75 __asm mov WORD PTR newCW, ax; // round down
76 __asm fldcw WORD PTR newCW;
77 __asm fistp DWORD PTR result;
78 __asm fldcw WORD PTR oldCW;
79 return result;
80#else
81 if (x > 0) {
82 return (int)x;
83 } else {
84 return (int)floor(x: x);
85 }
86#endif
87}
88
89static inline int splashCeil(SplashCoord x)
90{
91#if defined(USE_FLOAT)
92 return (int)ceilf(x);
93#elif defined(__GNUC__) && defined(__i386__)
94 // ceil() and (int)() are implemented separately, which results
95 // in changing the FPCW multiple times - so we optimize it with
96 // some inline assembly
97 unsigned short oldCW, newCW, t;
98 int result;
99
100 __asm__ volatile("fldl %4\n"
101 "fnstcw %0\n"
102 "movw %0, %3\n"
103 "andw $0xf3ff, %3\n"
104 "orw $0x0800, %3\n"
105 "movw %3, %1\n" // round up
106 "fldcw %1\n"
107 "fistpl %2\n"
108 "fldcw %0\n"
109 : "=m"(oldCW), "=m"(newCW), "=m"(result), "=r"(t)
110 : "m"(x));
111 return result;
112#elif defined(_WIN32) && defined(_M_IX86)
113 // ceil() and (int)() are implemented separately, which results
114 // in changing the FPCW multiple times - so we optimize it with
115 // some inline assembly
116 unsigned short oldCW, newCW;
117 int result;
118
119 __asm fld QWORD PTR x;
120 __asm fnstcw WORD PTR oldCW;
121 __asm mov ax, WORD PTR oldCW;
122 __asm and ax, 0xf3ff;
123 __asm or ax, 0x0800;
124 __asm mov WORD PTR newCW, ax; // round up
125 __asm fldcw WORD PTR newCW;
126 __asm fistp DWORD PTR result;
127 __asm fldcw WORD PTR oldCW;
128 return result;
129#else
130 return (int)ceil(x: x);
131#endif
132}
133
134static inline int splashRound(SplashCoord x)
135{
136#if defined(__GNUC__) && defined(__i386__)
137 // this could use round-to-nearest mode and avoid the "+0.5",
138 // but that produces slightly different results (because i+0.5
139 // sometimes rounds up and sometimes down using the even rule)
140 unsigned short oldCW, newCW, t;
141 int result;
142
143 x += 0.5;
144 __asm__ volatile("fldl %4\n"
145 "fnstcw %0\n"
146 "movw %0, %3\n"
147 "andw $0xf3ff, %3\n"
148 "orw $0x0400, %3\n"
149 "movw %3, %1\n" // round down
150 "fldcw %1\n"
151 "fistpl %2\n"
152 "fldcw %0\n"
153 : "=m"(oldCW), "=m"(newCW), "=m"(result), "=r"(t)
154 : "m"(x));
155 return result;
156#elif defined(_WIN32) && defined(_M_IX86)
157 // this could use round-to-nearest mode and avoid the "+0.5",
158 // but that produces slightly different results (because i+0.5
159 // sometimes rounds up and sometimes down using the even rule)
160 unsigned short oldCW, newCW;
161 int result;
162
163 x += 0.5;
164 __asm fld QWORD PTR x;
165 __asm fnstcw WORD PTR oldCW;
166 __asm mov ax, WORD PTR oldCW;
167 __asm and ax, 0xf3ff;
168 __asm or ax, 0x0400;
169 __asm mov WORD PTR newCW, ax; // round down
170 __asm fldcw WORD PTR newCW;
171 __asm fistp DWORD PTR result;
172 __asm fldcw WORD PTR oldCW;
173 return result;
174#else
175 return (int)splashFloor(x: x + 0.5);
176#endif
177}
178
179static inline SplashCoord splashAvg(SplashCoord x, SplashCoord y)
180{
181 return 0.5 * (x + y);
182}
183
184static inline SplashCoord splashSqrt(SplashCoord x)
185{
186#if defined(USE_FLOAT)
187 return sqrtf(x);
188#else
189 return sqrt(x: x);
190#endif
191}
192
193static inline SplashCoord splashPow(SplashCoord x, SplashCoord y)
194{
195#if defined(USE_FLOAT)
196 return powf(x, y);
197#else
198 return pow(x: x, y: y);
199#endif
200}
201
202static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1)
203{
204 SplashCoord dx, dy;
205 dx = x1 - x0;
206 dy = y1 - y0;
207 return splashSqrt(x: dx * dx + dy * dy);
208}
209
210static inline bool splashCheckDet(SplashCoord m11, SplashCoord m12, SplashCoord m21, SplashCoord m22, SplashCoord epsilon)
211{
212 return fabs(x: m11 * m22 - m12 * m21) >= epsilon;
213}
214
215#endif
216

source code of poppler/splash/SplashMath.h