]> granicus.if.org Git - icu/commitdiff
ICU-8915 flag & test for whether signed integer right shift is Arithmetic Shift Right
authorMarkus Scherer <markus.icu@gmail.com>
Thu, 1 Dec 2011 06:04:35 +0000 (06:04 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Thu, 1 Dec 2011 06:04:35 +0000 (06:04 +0000)
X-SVN-Rev: 30999

icu4c/source/common/normalizer2impl.cpp
icu4c/source/common/putilimp.h
icu4c/source/test/cintltst/putiltst.c

index e1c137d482d80ea809bb59890bc074e991de3e4b..ecbefdc6fcd5878e86c9b59dae6a879065bc21b0 100644 (file)
@@ -1008,7 +1008,12 @@ Normalizer2Impl::composePair(UChar32 a, UChar32 b) const {
     if(b<0 || 0x10ffff<b) {  // combine(list, b) requires a valid code point b
         return U_SENTINEL;
     }
+#if U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC
     return combine(list, b)>>1;
+#else
+    int32_t compositeAndFwd=combine(list, b);
+    return compositeAndFwd>=0 ? compositeAndFwd>>1 : U_SENTINEL;
+#endif
 }
 
 // Very similar to composeQuickCheck(): Make the same changes in both places if relevant.
index 1e324913c274a1ee7c0512b65b8b2d2ae8d87b8c..6d97dacfd178ed766ba5725d01ce93d0fb8314a8 100644 (file)
 #include "unicode/utypes.h"
 #include "unicode/putil.h"
 
+/**
+ * \def U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC
+ * Nearly all CPUs and compilers implement a right-shift of a signed integer
+ * as an Arithmetic Shift Right which copies the sign bit (the Most Significant Bit (MSB))
+ * into the vacated bits (sign extension).
+ * For example, (int32_t)0xfff5fff3>>4 becomes 0xffff5fff and -1>>1=-1.
+ *
+ * This can be useful for storing a signed value in the upper bits
+ * and another bit field in the lower bits.
+ * The signed value can be retrieved by simple right-shifting.
+ *
+ * This is consistent with the Java language.
+ *
+ * However, the C standard allows compilers to implement a right-shift of a signed integer
+ * as a Logical Shift Right which copies a 0 into the vacated bits.
+ * For example, (int32_t)0xfff5fff3>>4 becomes 0x0fff5fff and -1>>1=0x7fffffff.
+ *
+ * Code that depends on the natural behavior should be guarded with this macro,
+ * with an alternate path for unusual platforms.
+ * @internal
+ */
+#ifdef U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC
+    /* Use the predefined value. */
+#else
+    /*
+     * Nearly all CPUs & compilers implement a right-shift of a signed integer
+     * as an Arithmetic Shift Right (with sign extension).
+     */
+#   define U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC 1
+#endif
+
 /** Define this to 1 if your platform supports IEEE 754 floating point,
    to 0 if it does not. */
 #ifndef IEEE_754
index d4a3a466608490f8dee5d4d72c3216b84d3d4dfc..8d18f6cf56209cda9b5f494f70966de26f1cdf71 100644 (file)
 #include "uinvchar.h"
 #include <stdio.h>
 
+/* See the comments on U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC. */
+static void TestSignedRightShiftIsArithmetic() {
+    int32_t x=0xfff5fff3;
+    int32_t m=-1;
+    int32_t x4=x>>4;
+    int32_t m1=m>>1;
+    UBool signedRightShiftIsArithmetic= x4==0xffff5fff && m1==-1;
+    if(signedRightShiftIsArithmetic==U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC) {
+        log_info("signed right shift is Arithmetic Shift Right: %d\n",
+                 signedRightShiftIsArithmetic);
+    } else {
+        log_err("error: unexpected signed right shift is Arithmetic Shift Right: %d\n"
+                "       You need to change the value of U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC "
+                "for your platform.\n",
+                signedRightShiftIsArithmetic);
+    }
+}
 
 static UBool compareWithNAN(double x, double y);
 static void doAssert(double expect, double got, const char *message);
@@ -192,7 +209,6 @@ static void TestVersion(void)
     char versionString[17]; /* xxx.xxx.xxx.xxx\0 */
     UChar versionUString[] = { 0x0031, 0x002E, 0x0030, 0x002E,
                                0x0032, 0x002E, 0x0038, 0x0000 }; /* 1.0.2.8 */
-    UBool isModified = FALSE;
     UVersionInfo version;
     UErrorCode status = U_ZERO_ERROR;
 
@@ -674,6 +690,7 @@ static void toolutil_findDirname(void)
 static void addToolUtilTests(TestNode** root) {
     addTest(root, &toolutil_findBasename,       "putiltst/toolutil/findBasename");
     addTest(root, &toolutil_findDirname,       "putiltst/toolutil/findDirname");
+    addTest(root, &TestSignedRightShiftIsArithmetic, "putiltst/toolutil/TestSignedRightShiftIsArithmetic");
   /*
     Not yet tested: