1 /*
2 Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization
3 dedicated to making software imaging solutions freely available.
4
5 You may not use this file except in compliance with the License.
6 obtain a copy of the License at
7
8 http://www.imagemagick.org/script/license.php
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 MagickCore quantum inline methods.
17 */
18 #ifndef MAGICKCORE_QUANTUM_PRIVATE_H
19 #define MAGICKCORE_QUANTUM_PRIVATE_H
20
21 #include "MagickCore/cache.h"
22
23 #if defined(__cplusplus) || defined(c_plusplus)
24 extern "C" {
25 #endif
26
27 typedef struct _QuantumState
28 {
29 double
30 inverse_scale;
31
32 unsigned int
33 pixel;
34
35 size_t
36 bits;
37
38 const unsigned int
39 *mask;
40 } QuantumState;
41
42 struct _QuantumInfo
43 {
44 size_t
45 depth,
46 quantum;
47
48 QuantumFormatType
49 format;
50
51 double
52 minimum,
53 maximum,
54 scale;
55
56 size_t
57 pad;
58
59 MagickBooleanType
60 min_is_white,
61 pack;
62
63 QuantumAlphaType
64 alpha_type;
65
66 size_t
67 number_threads;
68
69 unsigned char
70 **pixels;
71
72 size_t
73 extent;
74
75 EndianType
76 endian;
77
78 QuantumState
79 state;
80
81 SemaphoreInfo
82 *semaphore;
83
84 size_t
85 signature;
86 };
87
88 extern MagickPrivate void
89 ResetQuantumState(QuantumInfo *);
90
GetQuantumRange(const size_t depth)91 static inline MagickSizeType GetQuantumRange(const size_t depth)
92 {
93 MagickSizeType
94 one;
95
96 one=1;
97 return((MagickSizeType) ((one << (depth-1))+((one << (depth-1))-1)));
98 }
99
HalfToSinglePrecision(const unsigned short half)100 static inline float HalfToSinglePrecision(const unsigned short half)
101 {
102 #define ExponentBias (127-15)
103 #define ExponentMask 0x7c00
104 #define ExponentShift 23
105 #define SignBitShift 31
106 #define SignificandShift 13
107 #define SignificandMask 0x00000400
108
109 typedef union _SinglePrecision
110 {
111 unsigned int
112 fixed_point;
113
114 float
115 single_precision;
116 } SinglePrecision;
117
118 register unsigned int
119 exponent,
120 significand,
121 sign_bit;
122
123 SinglePrecision
124 map;
125
126 unsigned int
127 value;
128
129 /*
130 The IEEE 754 standard specifies half precision as having:
131
132 Sign bit: 1 bit
133 Exponent width: 5 bits
134 Significand precision: 11 (10 explicitly stored)
135 */
136 sign_bit=(unsigned int) ((half >> 15) & 0x00000001);
137 exponent=(unsigned int) ((half >> 10) & 0x0000001f);
138 significand=(unsigned int) (half & 0x000003ff);
139 if (exponent == 0)
140 {
141 if (significand == 0)
142 value=sign_bit << SignBitShift;
143 else
144 {
145 while ((significand & SignificandMask) == 0)
146 {
147 significand<<=1;
148 exponent--;
149 }
150 exponent++;
151 significand&=(~SignificandMask);
152 exponent+=ExponentBias;
153 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
154 (significand << SignificandShift);
155 }
156 }
157 else
158 if (exponent == SignBitShift)
159 {
160 value=(sign_bit << SignBitShift) | 0x7f800000;
161 if (significand != 0)
162 value|=(significand << SignificandShift);
163 }
164 else
165 {
166 exponent+=ExponentBias;
167 significand<<=SignificandShift;
168 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
169 significand;
170 }
171 map.fixed_point=value;
172 return(map.single_precision);
173 }
174
PopCharPixel(const unsigned char pixel,unsigned char * pixels)175 static inline unsigned char *PopCharPixel(const unsigned char pixel,
176 unsigned char *pixels)
177 {
178 *pixels++=pixel;
179 return(pixels);
180 }
181
PopLongPixel(const EndianType endian,const unsigned int pixel,unsigned char * pixels)182 static inline unsigned char *PopLongPixel(const EndianType endian,
183 const unsigned int pixel,unsigned char *pixels)
184 {
185 register unsigned int
186 quantum;
187
188 quantum=(unsigned int) pixel;
189 if (endian == LSBEndian)
190 {
191 *pixels++=(unsigned char) (quantum);
192 *pixels++=(unsigned char) (quantum >> 8);
193 *pixels++=(unsigned char) (quantum >> 16);
194 *pixels++=(unsigned char) (quantum >> 24);
195 return(pixels);
196 }
197 *pixels++=(unsigned char) (quantum >> 24);
198 *pixels++=(unsigned char) (quantum >> 16);
199 *pixels++=(unsigned char) (quantum >> 8);
200 *pixels++=(unsigned char) (quantum);
201 return(pixels);
202 }
203
PopShortPixel(const EndianType endian,const unsigned short pixel,unsigned char * pixels)204 static inline unsigned char *PopShortPixel(const EndianType endian,
205 const unsigned short pixel,unsigned char *pixels)
206 {
207 register unsigned int
208 quantum;
209
210 quantum=pixel;
211 if (endian == LSBEndian)
212 {
213 *pixels++=(unsigned char) (quantum);
214 *pixels++=(unsigned char) (quantum >> 8);
215 return(pixels);
216 }
217 *pixels++=(unsigned char) (quantum >> 8);
218 *pixels++=(unsigned char) (quantum);
219 return(pixels);
220 }
221
PushCharPixel(const unsigned char * pixels,unsigned char * pixel)222 static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
223 unsigned char *pixel)
224 {
225 *pixel=(*pixels++);
226 return(pixels);
227 }
228
PushLongPixel(const EndianType endian,const unsigned char * pixels,unsigned int * pixel)229 static inline const unsigned char *PushLongPixel(const EndianType endian,
230 const unsigned char *pixels,unsigned int *pixel)
231 {
232 register unsigned int
233 quantum;
234
235 if (endian == LSBEndian)
236 {
237 quantum=((unsigned int) *pixels++);
238 quantum|=((unsigned int) *pixels++ << 8);
239 quantum|=((unsigned int) *pixels++ << 16);
240 quantum|=((unsigned int) *pixels++ << 24);
241 *pixel=quantum;
242 return(pixels);
243 }
244 quantum=((unsigned int) *pixels++ << 24);
245 quantum|=((unsigned int) *pixels++ << 16);
246 quantum|=((unsigned int) *pixels++ << 8);
247 quantum|=((unsigned int) *pixels++);
248 *pixel=quantum;
249 return(pixels);
250 }
251
PushShortPixel(const EndianType endian,const unsigned char * pixels,unsigned short * pixel)252 static inline const unsigned char *PushShortPixel(const EndianType endian,
253 const unsigned char *pixels,unsigned short *pixel)
254 {
255 register unsigned int
256 quantum;
257
258 if (endian == LSBEndian)
259 {
260 quantum=(unsigned int) *pixels++;
261 quantum|=(unsigned int) (*pixels++ << 8);
262 *pixel=(unsigned short) (quantum & 0xffff);
263 return(pixels);
264 }
265 quantum=(unsigned int) (*pixels++ << 8);
266 quantum|=(unsigned int) *pixels++;
267 *pixel=(unsigned short) (quantum & 0xffff);
268 return(pixels);
269 }
270
ScaleAnyToQuantum(const QuantumAny quantum,const QuantumAny range)271 static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
272 const QuantumAny range)
273 {
274 if (quantum > range)
275 return(QuantumRange);
276 #if !defined(MAGICKCORE_HDRI_SUPPORT)
277 return((Quantum) (((double) QuantumRange*quantum)/range+0.5));
278 #else
279 return((Quantum) (((double) QuantumRange*quantum)/range));
280 #endif
281 }
282
ScaleQuantumToAny(const Quantum quantum,const QuantumAny range)283 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
284 const QuantumAny range)
285 {
286 return((QuantumAny) (((double) range*quantum)/QuantumRange+0.5));
287 }
288
289 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
ScaleCharToQuantum(const unsigned char value)290 static inline Quantum ScaleCharToQuantum(const unsigned char value)
291 {
292 return((Quantum) value);
293 }
294
ScaleLongToQuantum(const unsigned int value)295 static inline Quantum ScaleLongToQuantum(const unsigned int value)
296 {
297 #if !defined(MAGICKCORE_HDRI_SUPPORT)
298 return((Quantum) ((value+8421504UL)/16843009UL));
299 #else
300 return((Quantum) (value/16843009.0));
301 #endif
302 }
303
ScaleLongLongToQuantum(const MagickSizeType value)304 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
305 {
306 #if !defined(MAGICKCORE_HDRI_SUPPORT)
307 return((Quantum) ((value+MagickULLConstant(551911719039))/
308 MagickULLConstant(1103823438079)));
309 #else
310 return((Quantum) (value/1103823438079.0));
311 #endif
312 }
313
ScaleMapToQuantum(const MagickRealType value)314 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
315 {
316 if (value <= 0.0)
317 return((Quantum) 0);
318 if (value >= MaxMap)
319 return(QuantumRange);
320 #if !defined(MAGICKCORE_HDRI_SUPPORT)
321 return((Quantum) (value+0.5));
322 #else
323 return((Quantum) value);
324 #endif
325 }
326
ScaleQuantumToLong(const Quantum quantum)327 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
328 {
329 #if !defined(MAGICKCORE_HDRI_SUPPORT)
330 return((unsigned int) (16843009UL*quantum));
331 #else
332 if (quantum <= 0.0)
333 return(0UL);
334 if ((16843009.0*quantum) >= 4294967295.0)
335 return(4294967295UL);
336 return((unsigned int) (16843009.0*quantum+0.5));
337 #endif
338 }
339
ScaleQuantumToLongLong(const Quantum quantum)340 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
341 {
342 #if !defined(MAGICKCORE_HDRI_SUPPORT)
343 return((MagickSizeType) (MagickULLConstant(551911719039)*quantum));
344 #else
345 if (quantum <= 0.0)
346 return(0UL);
347 if ((551911719039.0*quantum) >= 18446744073709551615.0)
348 return(MagickULLConstant(18446744073709551615));
349 return((MagickSizeType) (1103823438079.0*quantum+0.5));
350 #endif
351 }
352
ScaleQuantumToMap(const Quantum quantum)353 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
354 {
355 if (quantum >= (Quantum) MaxMap)
356 return((unsigned int) MaxMap);
357 #if !defined(MAGICKCORE_HDRI_SUPPORT)
358 return((unsigned int) quantum);
359 #else
360 if (quantum < 0.0)
361 return(0UL);
362 return((unsigned int) (quantum+0.5));
363 #endif
364 }
365
ScaleQuantumToShort(const Quantum quantum)366 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
367 {
368 #if !defined(MAGICKCORE_HDRI_SUPPORT)
369 return((unsigned short) (257UL*quantum));
370 #else
371 if (quantum <= 0.0)
372 return(0);
373 if ((257.0*quantum) >= 65535.0)
374 return(65535);
375 return((unsigned short) (257.0*quantum+0.5));
376 #endif
377 }
378
ScaleShortToQuantum(const unsigned short value)379 static inline Quantum ScaleShortToQuantum(const unsigned short value)
380 {
381 #if !defined(MAGICKCORE_HDRI_SUPPORT)
382 return((Quantum) ((value+128U)/257U));
383 #else
384 return((Quantum) (value/257.0));
385 #endif
386 }
387 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
ScaleCharToQuantum(const unsigned char value)388 static inline Quantum ScaleCharToQuantum(const unsigned char value)
389 {
390 #if !defined(MAGICKCORE_HDRI_SUPPORT)
391 return((Quantum) (257U*value));
392 #else
393 return((Quantum) (257.0*value));
394 #endif
395 }
396
ScaleLongToQuantum(const unsigned int value)397 static inline Quantum ScaleLongToQuantum(const unsigned int value)
398 {
399 #if !defined(MAGICKCORE_HDRI_SUPPORT)
400 return((Quantum) ((value+MagickULLConstant(32768))/
401 MagickULLConstant(65537)));
402 #else
403 return((Quantum) (value/65537.0));
404 #endif
405 }
406
ScaleLongLongToQuantum(const MagickSizeType value)407 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
408 {
409 #if !defined(MAGICKCORE_HDRI_SUPPORT)
410 return((Quantum) ((value+MagickULLConstant(8421376))/
411 MagickULLConstant(16842752)));
412 #else
413 return((Quantum) (value/16842752.0));
414 #endif
415 }
416
ScaleMapToQuantum(const MagickRealType value)417 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
418 {
419 if (value <= 0.0)
420 return((Quantum) 0);
421 if (value >= MaxMap)
422 return(QuantumRange);
423 #if !defined(MAGICKCORE_HDRI_SUPPORT)
424 return((Quantum) (value+0.5));
425 #else
426 return((Quantum) value);
427 #endif
428 }
429
ScaleQuantumToLong(const Quantum quantum)430 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
431 {
432 #if !defined(MAGICKCORE_HDRI_SUPPORT)
433 return((unsigned int) (65537UL*quantum));
434 #else
435 if (quantum <= 0.0)
436 return(0UL);
437 if ((65537.0*quantum) >= 4294967295.0)
438 return(4294967295U);
439 return((unsigned int) (65537.0*quantum+0.5));
440 #endif
441 }
442
ScaleQuantumToLongLong(const Quantum quantum)443 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
444 {
445 #if !defined(MAGICKCORE_HDRI_SUPPORT)
446 return((MagickSizeType) (MagickULLConstant(16842752)*quantum));
447 #else
448 if (quantum <= 0.0)
449 return(0UL);
450 if ((65537.0*quantum) >= 18446744073709551615.0)
451 return(MagickULLConstant(18446744073709551615));
452 return((MagickSizeType) (16842752.0*quantum+0.5));
453 #endif
454 }
455
ScaleQuantumToMap(const Quantum quantum)456 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
457 {
458 if (quantum >= (Quantum) MaxMap)
459 return((unsigned int) MaxMap);
460 #if !defined(MAGICKCORE_HDRI_SUPPORT)
461 return((unsigned int) quantum);
462 #else
463 if (quantum < 0.0)
464 return(0UL);
465 return((unsigned int) (quantum+0.5));
466 #endif
467 }
468
ScaleQuantumToShort(const Quantum quantum)469 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
470 {
471 #if !defined(MAGICKCORE_HDRI_SUPPORT)
472 return((unsigned short) quantum);
473 #else
474 if (quantum <= 0.0)
475 return(0);
476 if (quantum >= 65535.0)
477 return(65535);
478 return((unsigned short) (quantum+0.5));
479 #endif
480 }
481
ScaleShortToQuantum(const unsigned short value)482 static inline Quantum ScaleShortToQuantum(const unsigned short value)
483 {
484 return((Quantum) value);
485 }
486 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
ScaleCharToQuantum(const unsigned char value)487 static inline Quantum ScaleCharToQuantum(const unsigned char value)
488 {
489 #if !defined(MAGICKCORE_HDRI_SUPPORT)
490 return((Quantum) (16843009UL*value));
491 #else
492 return((Quantum) (16843009.0*value));
493 #endif
494 }
495
ScaleLongToQuantum(const unsigned int value)496 static inline Quantum ScaleLongToQuantum(const unsigned int value)
497 {
498 return((Quantum) value);
499 }
500
ScaleLongLongToQuantum(const MagickSizeType value)501 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
502 {
503 return((Quantum) value);
504 }
505
ScaleMapToQuantum(const MagickRealType value)506 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
507 {
508 if (value <= 0.0)
509 return((Quantum) 0);
510 if (value >= (Quantum) MaxMap)
511 return(QuantumRange);
512 #if !defined(MAGICKCORE_HDRI_SUPPORT)
513 return((Quantum) (65537.0*value+0.5));
514 #else
515 return((Quantum) (65537.0*value));
516 #endif
517 }
518
ScaleQuantumToLong(const Quantum quantum)519 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
520 {
521 #if !defined(MAGICKCORE_HDRI_SUPPORT)
522 return((unsigned int) quantum);
523 #else
524 if (quantum <= 0.0)
525 return(0);
526 if ((quantum) >= 4294967295.0)
527 return(4294967295);
528 return((unsigned int) (quantum+0.5));
529 #endif
530 }
531
ScaleQuantumToLongLong(const Quantum quantum)532 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
533 {
534 #if !defined(MAGICKCORE_HDRI_SUPPORT)
535 return((MagickSizeType) quantum);
536 #else
537 return((MagickSizeType) (quantum+0.5));
538 #endif
539 }
540
ScaleQuantumToMap(const Quantum quantum)541 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
542 {
543 if (quantum < 0.0)
544 return(0UL);
545 if ((quantum/65537) >= (Quantum) MaxMap)
546 return((unsigned int) MaxMap);
547 #if !defined(MAGICKCORE_HDRI_SUPPORT)
548 return((unsigned int) ((quantum+MagickULLConstant(32768))/
549 MagickULLConstant(65537)));
550 #else
551 return((unsigned int) (quantum/65537.0+0.5));
552 #endif
553 }
554
ScaleQuantumToShort(const Quantum quantum)555 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
556 {
557 #if !defined(MAGICKCORE_HDRI_SUPPORT)
558 return((unsigned short) ((quantum+MagickULLConstant(32768))/
559 MagickULLConstant(65537)));
560 #else
561 if (quantum <= 0.0)
562 return(0);
563 if ((quantum/65537.0) >= 65535.0)
564 return(65535);
565 return((unsigned short) (quantum/65537.0+0.5));
566 #endif
567 }
568
ScaleShortToQuantum(const unsigned short value)569 static inline Quantum ScaleShortToQuantum(const unsigned short value)
570 {
571 #if !defined(MAGICKCORE_HDRI_SUPPORT)
572 return((Quantum) (65537UL*value));
573 #else
574 return((Quantum) (65537.0*value));
575 #endif
576 }
577 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
ScaleCharToQuantum(const unsigned char value)578 static inline Quantum ScaleCharToQuantum(const unsigned char value)
579 {
580 return((Quantum) (72340172838076673.0*value));
581 }
582
ScaleLongToQuantum(const unsigned int value)583 static inline Quantum ScaleLongToQuantum(const unsigned int value)
584 {
585 return((Quantum) (4294967297.0*value));
586 }
587
ScaleLongLongToQuantum(const MagickSizeType value)588 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
589 {
590 return((Quantum) (18446744073709551615.0*value));
591 }
592
ScaleMapToQuantum(const MagickRealType value)593 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
594 {
595 if (value <= 0.0)
596 return((Quantum) 0);
597 if (value >= MaxMap)
598 return(QuantumRange);
599 return((Quantum) (281479271743489.0*value));
600 }
601
ScaleQuantumToLong(const Quantum quantum)602 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
603 {
604 return((unsigned int) (quantum/4294967297.0+0.5));
605 }
606
ScaleQuantumToLongLong(const Quantum quantum)607 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
608 {
609 return((MagickSizeType) (quantum/18446744073709551615.0+0.5));
610 }
611
ScaleQuantumToMap(const Quantum quantum)612 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
613 {
614 if (quantum <= 0.0)
615 return(0UL);
616 if ((quantum/281479271743489.0) >= MaxMap)
617 return((unsigned int) MaxMap);
618 return((unsigned int) (quantum/281479271743489.0+0.5));
619 }
620
ScaleQuantumToShort(const Quantum quantum)621 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
622 {
623 if (quantum <= 0.0)
624 return(0);
625 if ((quantum/281479271743489.0) >= 65535.0)
626 return(65535);
627 return((unsigned short) (quantum/281479271743489.0+0.5));
628 }
629
ScaleShortToQuantum(const unsigned short value)630 static inline Quantum ScaleShortToQuantum(const unsigned short value)
631 {
632 return((Quantum) (281479271743489.0*value));
633 }
634 #endif
635
SinglePrecisionToHalf(const float value)636 static inline unsigned short SinglePrecisionToHalf(const float value)
637 {
638 typedef union _SinglePrecision
639 {
640 unsigned int
641 fixed_point;
642
643 float
644 single_precision;
645 } SinglePrecision;
646
647 register int
648 exponent;
649
650 register unsigned int
651 significand,
652 sign_bit;
653
654 SinglePrecision
655 map;
656
657 unsigned short
658 half;
659
660 /*
661 The IEEE 754 standard specifies half precision as having:
662
663 Sign bit: 1 bit
664 Exponent width: 5 bits
665 Significand precision: 11 (10 explicitly stored)
666 */
667 map.single_precision=value;
668 sign_bit=(map.fixed_point >> 16) & 0x00008000;
669 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
670 significand=map.fixed_point & 0x007fffff;
671 if (exponent <= 0)
672 {
673 int
674 shift;
675
676 if (exponent < -10)
677 return((unsigned short) sign_bit);
678 significand=significand | 0x00800000;
679 shift=(int) (14-exponent);
680 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
681 ((significand >> shift) & 0x01)) >> shift);
682 return((unsigned short) (sign_bit | significand));
683 }
684 else
685 if (exponent == (0xff-ExponentBias))
686 {
687 if (significand == 0)
688 return((unsigned short) (sign_bit | ExponentMask));
689 else
690 {
691 significand>>=SignificandShift;
692 half=(unsigned short) (sign_bit | significand |
693 (significand == 0) | ExponentMask);
694 return(half);
695 }
696 }
697 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
698 if ((significand & 0x00800000) != 0)
699 {
700 significand=0;
701 exponent++;
702 }
703 if (exponent > 30)
704 {
705 float
706 alpha;
707
708 register int
709 i;
710
711 /*
712 Float overflow.
713 */
714 alpha=1.0e10;
715 for (i=0; i < 10; i++)
716 alpha*=alpha;
717 return((unsigned short) (sign_bit | ExponentMask));
718 }
719 half=(unsigned short) (sign_bit | (exponent << 10) |
720 (significand >> SignificandShift));
721 return(half);
722 }
723
724 #if defined(__cplusplus) || defined(c_plusplus)
725 }
726 #endif
727
728 #endif
729