CompareOps.java

/*
** Module   : CompareOps.java
** Abstract : Progress 4GL compatible CompareOps object
**
** Copyright (c) 2005-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- -----------------------------Description-----------------------------
** 001 GES 20050519   @21247 Created initial version with full support for all Progress comparison
**                           processing including all functions and logical operators.
** 002 GES 20050607   @21441 Minor additions for function support.
** 003 GES 20060303   @24881 Added unknown value helpers.
** 004 GES 20060620   @27477 Fixed unknown value processing for greater than and less than
**                           operators. Massive updates to the javadoc to fully document the
**                           behavior.
** 005 SIY 20070911   @35038 Workaround for some cases of string comparison for equality 
**                           (unknown vs "?"). Ref: 35039.
** 006 GES 20080402   @37824 Added signatures to allow widget references to be compared with
**                           handle types and each other.
** 007 GES 20081003   @40034 Added signatures for operators which can return boolean instead of
**                           logical, where those signatures were missing. 
** 008 CA  20090227   @41384 Added _isUnknown(String) method - return true if parameter is null.
** 009 CA  20090413   @41783 Added isUnknown(String) method, which returns Progress logical true
**                           if parameter is null. Minor cleanup.
** 010 OM  20130402   @41783 Switched to 64-bit long instead of 32 bit int.
** 011 OM  20150415          Rollback H005. Behavior was the result of LITERAL-QUESTION attribute.
** 012 VVT 20191119          Special case: an empty comhandle is considered be equal to the zero 
**                           integer. See #3820-170.
** 013 CA  20200304          Allow unknown tests for Java instances from 4GL code.
** 014 CA  20220620          Any equality compare between a legacy Text (longchar/character) instance and  
**                           another type will force compare as character.
** 015 CA  20231129          Avoid additional BDT creation for some operators which receive Java arguments.
** 016 CA  20240324          Use logical constants for TRUE, FALSE, UNKNOWN, within internal FWD runtime.
** 017 ICP 20250129          Used int64.of to leverage caches instances.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.util;

/**
 * A class that provides Progress 4GL compatible comparison functions and
 * logical operators.  This class provides all functionality as statics and
 * has no instance data.
 * <p>
 * The following is the mapping of Progress language features to the
 * corresponding feature in this class:
 * <p>
 * <pre>
 * =  or EQ operator                       {@link #isEqual}
 * &lt;&gt; or NE operator                       {@link #isNotEqual}
 * &gt;  or GT operator                       {@link #isGreaterThan}
 * &gt;= or GE operator                       {@link #isGreaterThanOrEqual}
 * &lt;  or LT operator                       {@link #isLessThan}
 * &lt;= or LE operator                       {@link #isLessThanOrEqual}
 * maximum  function                       {@link #maximum(BaseDataType[])}
 * minimum  function                       {@link #minimum(BaseDataType[])}
 * </pre>
 * <p>
 * The above methods all return an instance of {@link logical} which allows 
 * the Progress unknown value to be properly handled.  Each method is
 * heavily overloaded to support the possible variants of Java primitive
 * types as parameters.  A duplicate version of each of the operators 
 * exists under a name without the 'is' prefix, which returns
 * <code>boolean</code> as a convenience (WARNING: these duplicates
 * do not have all overloaded variants to support all primitive types as
 * do the versions that return a <code>logical</code>).
 * <p>
 * This class implements common unknown value logic for all operators and
 * functions, which is summarized by the following table of results (whether
 * the unknown value is in the left or right operand makes no difference):
 * <p>
 * <pre>
 * Operator                One Operand Unknown       Both Operands Unknown
 * --------------------    ---------------------     ----------------------
 * isEqual                 false                     true
 * isNotEqual              true                      false
 * isGreaterThan           unknown value             false
 * isLessThan              unknown value             false
 * isGreaterThanOrEqual    unknown value             true
 * isLessThanOrEqual       unknown value             true
 * </pre>
 * <p>
 * If any parameter of the {@link #minimum} or {@link #maximum} methods
 * is unknown, the result is unknown. 
 * <p>
 * Helper methods exist to test if an instance is <code>unknown</code>
 * {@link #isUnknown} (and {@link #_isUnknown}) or is not <code>unknown</code>
 * {@link #notUnknown} (and {@link #_notUnknown}). They return a 
 * <code>logical</code> or <code>boolean</code> type which makes them a
 * simpler form to use in expressions instead of
 * <code>isEqual(new unknown())</code>.
 *
 * @author    GES
 */
public class CompareOps
{
   /**
    * Returns the instance from the list which is the largest.  This
    * list may not include <code>null</code> values and all values must
    * be of the same subclass in order for the results to make sense.
    *
    * @param    list
    *           The list of objects to check.
    *
    * @return   The largest instance or an instance of 
    *           <code>unknown value</code> if any entry in the list is
    *           unknown or <code>null</code> if an empty list is passed.
    */
   public static BaseDataType maximum(BaseDataType[] list)
   {
      if (list.length == 0)
      {
         return null;
      }
      
      BaseDataType largest = list[0];
      
      for (int i = 1; i < list.length; i++)
      {
         largest = largest.maximum(list[i]);
      }
      
      return largest;
   }
      
   /**
    * Returns the smallest instance from the list.  This list may not
    * include <code>null</code> values and all values must
    * be of the same subclass in order for the results to make sense.
    *
    * @param    list
    *           The list of objects to check.
    *
    * @return   The smallest instance or an instance of 
    *           <code>unknown value</code> if any entry in the list is
    *           unknown or <code>null</code> if an empty list is passed.
    */
   public static BaseDataType minimum(BaseDataType[] list)
   {
      if (list.length == 0)
      {
         return null;
      }
      
      BaseDataType smallest = list[0];
      
      for (int i = 1; i < list.length; i++)
      {
         smallest = smallest.minimum(list[i]);
      }
      
      return smallest;
   }
      
   /**
    * Determines if the operand represents the <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is <code>unknown</code>.
    */
   public static boolean _isUnknown(BaseDataType op)
   {
      return op.isUnknown();
   }

   /**
    * Determines if the operand represents the <code>unknown value</code>.
    * For a <code>null</code> value, this method will return true. 
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is <code>unknown</code>.
    */
   public static boolean _isUnknown(String op)
   {
      return op == null;
   }
   
   /**
    * Determines if the operand represents the <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is <code>unknown</code>.
    */
   public static boolean _isUnknown(WrappedResource op)
   {
      return op == null || op.unknown();
   }
   
   /**
    * Determines if the operand represents the <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   Logical <code>true</code> if the object is 
    *           <code>unknown</code>.
    */
   public static logical isUnknown(BaseDataType op)
   {
      return logical.of(op.isUnknown());
   }
   
   /**
    * Determines if the operand represents the <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   Logical <code>true</code> if the object is 
    *           <code>unknown</code>.
    */
   public static logical isUnknown(WrappedResource op)
   {
      return isUnknown(new handle(op));
   }
   
   /**
    * Determines if the operand represents the <code>unknown value</code>.
    * For a <code>null</code> value, this method will return true. 
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is <code>unknown</code>.
    */
   public static logical isUnknown(String op)
   {
      return logical.of(op == null);
   }

   /**
    * For a <code>null</code> value, this method will return true. 
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is <code>null</code>.
    */
   public static logical isUnknown(Object op)
   {
      return logical.of(op == null);
   }
   
   /**
    * Determines if the operand does NOT represent the
    * <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is NOT <code>unknown</code>.
    */
   public static boolean _notUnknown(BaseDataType op)
   {
      return !op.isUnknown();
   }
   
   /**
    * Determines if the operand does NOT represent the
    * <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is NOT <code>unknown</code>.
    */
   public static boolean _notUnknown(WrappedResource op)
   {
      return op != null && !op.unknown();
   }
   
   /**
    * Determines if the operand does NOT represent the
    * <code>null value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   <code>true</code> if the object is NOT <code>null</code>.
    */
   public static boolean _notUnknown(Object op)
   {
      return op != null;
   }

   /**
    * Determines if the operand does NOT represent the
    * <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   Logical <code>true</code> if the object is NOT 
    *           <code>unknown</code>.
    */
   public static logical notUnknown(BaseDataType op)
   {
      return logical.of(!op.isUnknown());
   }
   
   /**
    * Determines if the operand does NOT represent the
    * <code>unknown value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   Logical <code>true</code> if the object is NOT 
    *           <code>unknown</code>.
    */
   public static logical notUnknown(WrappedResource op)
   {
      return notUnknown(new handle(op));
   }
   
   /**
    * Determines if the operand does NOT represent the
    * <code>null value</code>.
    *
    * @param    op
    *           The instance to test.
    *
    * @return   Logical <code>true</code> if the object is NOT 
    *           <code>null</code>.
    */
   public static logical notUnknown(Object op)
   {
      return logical.of(op != null);
   }
   
   /**
    * Determines if the two operands are equivalent.
    *
    * @param   op1
    *          The left operand.
    * @param   op2
    *          The right operand.
    *
    * @return  {@code true} if the operands are the same or if both operands are {@code unknown}.
    */
   public static boolean equals(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown();
      
      // special case: an empty comhandle is considered be equal to the zero integer
      if ((u1 && !u2 && (op1 instanceof comhandle) && (op2 instanceof int64)
              && ((int64) op2).getValue() == 0L) ||
          (u2 && !u1 && (op2 instanceof comhandle) && (op1 instanceof int64)
              && ((int64) op1).getValue() == 0L))
      {
         return true;
      }
      
      if (u1 && u2)
      {
         return true;
      }
      
      if (u1 || u2)
      {
         return false;
      }
      
      if (op2 instanceof Text && !(op1 instanceof Text))
      {
         // compare string representation
         return equals(new character(op1), op2);
      }
      
      if (op1 instanceof Text && !(op2 instanceof Text))
      {
         // compare string representation
         return equals(op1, new character(op2));
      }
      
      return op1.compareTo(op2) == 0;
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static boolean _isEqual(BaseDataType op1, BaseDataType op2)
   {
      return equals(op1, op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static boolean _isEqual(WrappedResource op1, BaseDataType op2)
   {
      return equals(new handle(op1), op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static boolean _isEqual(BaseDataType op1, WrappedResource op2)
   {
      return equals(op1, new handle(op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static boolean _isEqual(WrappedResource op1, WrappedResource op2)
   {
      return equals(new handle(op1), new handle(op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(boolean op1, BaseDataType op2)
   {
      return equals(logical.of(op1), op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(BaseDataType op1, boolean op2)
   {
      return equals(op1, logical.of(op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(boolean op1, boolean op2)
   {
      // INLINED for efficiency...
      return (op1 == op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(String op1, BaseDataType op2)
   {
      return equals(new character(op1), op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(BaseDataType op1, String op2)
   {
      return equals(op1, new character(op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return (result == 0);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(long op1, BaseDataType op2)
   {
      return equals(int64.of(op1), op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(BaseDataType op1, long op2)
   {
      return equals(op1, int64.of(op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return (op1 == op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(double op1, BaseDataType op2)
   {
      return equals(new decimal(op1), op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(BaseDataType op1, double op2)
   {
      return equals(op1, new decimal(op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static boolean _isEqual(double op1, double op2)
   {
      // also matches int == double and double == int cases
      return equals(new decimal(op1), new decimal(op2));
   }
   
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static logical isEqual(BaseDataType op1, BaseDataType op2)
   {
      return logical.of(equals(op1, op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static logical isEqual(WrappedResource op1, BaseDataType op2)
   {
      return logical.of(equals(new handle(op1), op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static logical isEqual(BaseDataType op1, WrappedResource op2)
   {
      return logical.of(equals(op1, new handle(op2)));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same or if both
    *           operands are <code>unknown</code>.
    */
   public static logical isEqual(WrappedResource op1, WrappedResource op2)
   {
      return logical.of(equals(new handle(op1), new handle(op2)));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(boolean op1, BaseDataType op2)
   {
      return logical.of(equals(logical.of(op1), op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(BaseDataType op1, boolean op2)
   {
      return logical.of(equals(op1, logical.of(op2)));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(boolean op1, boolean op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 == op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(String op1, BaseDataType op2)
   {
      return logical.of(equals(new character(op1), op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(BaseDataType op1, String op2)
   {
      return logical.of(equals(op1, new character(op2)));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return logical.of(result == 0);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(long op1, BaseDataType op2)
   {
      return logical.of(equals(int64.of(op1), op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(BaseDataType op1, long op2)
   {
      return logical.of(equals(op1, int64.of(op2)));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 == op2);
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(double op1, BaseDataType op2)
   {
      return logical.of(equals(new decimal(op1), op2));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(BaseDataType op1, double op2)
   {
      return logical.of(equals(op1, new decimal(op2)));
   }
      
   /**
    * Determines if the two operands are equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the operands are the same.
    */
   public static logical isEqual(double op1, double op2)
   {
      // also matches int == double and double == int cases
      return logical.of(equals(new decimal(op1), new decimal(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static boolean notEqual(BaseDataType op1, BaseDataType op2)
   {
      return !equals(op1, op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static boolean _isNotEqual(BaseDataType op1, BaseDataType op2)
   {
      return notEqual(op1, op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static boolean _isNotEqual(WrappedResource op1, BaseDataType op2)
   {
      return notEqual(new handle(op1), op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static boolean _isNotEqual(BaseDataType op1, WrappedResource op2)
   {
      return notEqual(op1, new handle(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static boolean _isNotEqual(WrappedResource op1, WrappedResource op2)
   {
      return notEqual(new handle(op1), new handle(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(boolean op1, BaseDataType op2)
   {
      return notEqual(logical.of(op1), op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(BaseDataType op1, boolean op2)
   {
      return notEqual(op1, logical.of(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static boolean _isNotEqual(boolean op1, boolean op2)
   {
      // INLINED for efficiency...
      return (op1 != op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(String op1, BaseDataType op2)
   {
      return notEqual(new character(op1), op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(BaseDataType op1, String op2)
   {
      return notEqual(op1, new character(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static boolean _isNotEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return (result != 0);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(long op1, BaseDataType op2)
   {
      return notEqual(int64.of(op1), op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(BaseDataType op1, long op2)
   {
      return notEqual(op1, int64.of(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static boolean _isNotEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return (op1 != op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(double op1, BaseDataType op2)
   {
      return notEqual(new decimal(op1), op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static boolean _isNotEqual(BaseDataType op1, double op2)
   {
      return notEqual(op1, new decimal(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static boolean _isNotEqual(double op1, double op2)
   {
      // also matches the double != int and int != double cases
      return notEqual(new decimal(op1), new decimal(op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static logical isNotEqual(BaseDataType op1, BaseDataType op2)
   {
      return logical.of(notEqual(op1, op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static logical isNotEqual(WrappedResource op1, BaseDataType op2)
   {
      return logical.of(notEqual(new handle(op1), op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static logical isNotEqual(BaseDataType op1, WrappedResource op2)
   {
      return logical.of(notEqual(op1, new handle(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if either of the operands is <code>unknown</code> while the
    *           other is not.
    */
   public static logical isNotEqual(WrappedResource op1, WrappedResource op2)
   {
      return logical.of(notEqual(new handle(op1), new handle(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static logical isNotEqual(boolean op1, BaseDataType op2)
   {
      return logical.of(notEqual(logical.of(op1), op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static logical isNotEqual(BaseDataType op1, boolean op2)
   {
      return logical.of(notEqual(op1, logical.of(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static logical isNotEqual(boolean op1, boolean op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 != op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static logical isNotEqual(String op1, BaseDataType op2)
   {
      return logical.of(notEqual(new character(op1), op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static logical isNotEqual(BaseDataType op1, String op2)
   {
      return logical.of(notEqual(op1, new character(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static logical isNotEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return logical.of(result != 0);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static logical isNotEqual(long op1, BaseDataType op2)
   {
      return logical.of(notEqual(int64.of(op1), op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static logical isNotEqual(BaseDataType op1, long op2)
   {
      return logical.of(notEqual(op1, int64.of(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static logical isNotEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 != op2);
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the right operand is <code>unknown</code>.
    */
   public static logical isNotEqual(double op1, BaseDataType op2)
   {
      return logical.of(notEqual(new decimal(op1), op2));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same OR
    *           if the left operand is <code>unknown</code>.
    */
   public static logical isNotEqual(BaseDataType op1, double op2)
   {
      return logical.of(notEqual(op1, new decimal(op2)));
   }
      
   /**
    * Determines if the two operands are <b>not</b> equivalent.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the objects are <b>not</b> the same.
    */
   public static logical isNotEqual(double op1, double op2)
   {
      // also matches the double != int and int != double cases
      return logical.of(notEqual(new decimal(op1), new decimal(op2)));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand OR when either
    *           or both of the operands are <code>unknown</code>.
    */
   public static boolean greaterThan(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 || u2)
         return false;
            
      return (op1.compareTo(op2) > 0);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand OR if either or
    *           both operands are <code>unknown</code>.
    */
   public static boolean _isGreaterThan(BaseDataType op1, BaseDataType op2)
   {
      return greaterThan(op1, op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(boolean op1, BaseDataType op2)
   {
      return greaterThan(logical.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(BaseDataType op1, boolean op2)
   {
      return greaterThan(op1, logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static boolean _isGreaterThan(boolean op1, boolean op2)
   {
      return greaterThan(logical.of(op1), logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(String op1, BaseDataType op2)
   {
      return greaterThan(new character(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(BaseDataType op1, String op2)
   {
      return greaterThan(op1, new character(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static boolean _isGreaterThan(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return (result > 0);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(long op1, BaseDataType op2)
   {
      return greaterThan(new int64(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(BaseDataType op1, long op2)
   {
      return greaterThan(op1, int64.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static boolean _isGreaterThan(long op1, long op2)
   {
      // INLINED for efficiency...
      return (op1 > op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(double op1, BaseDataType op2)
   {
      return greaterThan(new decimal(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThan(BaseDataType op1, double op2)
   {
      return greaterThan(op1, new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static boolean _isGreaterThan(double op1, double op2)
   {
      // also handles double > int and int > double cases
      return greaterThan(new decimal(op1), new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand OR if both
    *           operands are <code>unknown</code>.  <code>unknown</code>
    *           when any one operand is <code>unknown</code> and the other
    *           is not.
    */
   public static logical isGreaterThan(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 && u2) 
         return logical.of(false);
      
      if (u1 || u2)
         return logical.UNKNOWN;
      
      return logical.of(op1.compareTo(op2) > 0);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(boolean op1, BaseDataType op2)
   {
      return isGreaterThan(logical.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(BaseDataType op1, boolean op2)
   {
      return isGreaterThan(op1, logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static logical isGreaterThan(boolean op1, boolean op2)
   {
      return isGreaterThan(logical.of(op1), logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(String op1, BaseDataType op2)
   {
      return isGreaterThan(new character(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(BaseDataType op1, String op2)
   {
      return isGreaterThan(op1, new character(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static logical isGreaterThan(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return logical.of(result > 0);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(long op1, BaseDataType op2)
   {
      return isGreaterThan(int64.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(BaseDataType op1, long op2)
   {
      return isGreaterThan(op1, int64.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static logical isGreaterThan(long op1, long op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 > op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(double op1, BaseDataType op2)
   {
      return isGreaterThan(new decimal(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isGreaterThan(BaseDataType op1, double op2)
   {
      return isGreaterThan(op1, new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than the
    *           right operand. <code>false</code> if the left operand
    *           is less than or equal to the right operand.
    */
   public static logical isGreaterThan(double op1, double op2)
   {
      // also handles double > int and int > double cases
      return isGreaterThan(new decimal(op1), new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand OR if both operands are
    *           <code>unknown</code>.  <code>false</code> if the left operand
    *           is less than the right operand OR when any one operand is
    *           <code>unknown</code> and the other is not.
    */
   public static boolean greaterThanOrEqual(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 && u2) 
         return true;
      
      if (u1 || u2)
         return false;
            
      return (op1.compareTo(op2) >= 0);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand OR if both operands are
    *           <code>unknown</code>.  <code>false</code> if the left operand
    *           is less than the right operand.  <code>unknown</code>
    *           when any one operand is <code>unknown</code> and the other
    *           is not.
    */
   public static boolean _isGreaterThanOrEqual(BaseDataType op1, BaseDataType op2)
   {
      return greaterThanOrEqual(op1, op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(BaseDataType op1, boolean op2)
   {
      return greaterThanOrEqual(op1, logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(boolean op1, BaseDataType op2)
   {
      return greaterThanOrEqual(logical.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static boolean _isGreaterThanOrEqual(boolean op1, boolean op2)
   {
      return greaterThanOrEqual(logical.of(op1), logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(BaseDataType op1, String op2)
   {
      return greaterThanOrEqual(op1, new character(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(String op1, BaseDataType op2)
   {
      return greaterThanOrEqual(new character(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static boolean _isGreaterThanOrEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return (result >= 0);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(BaseDataType op1, long op2)
   {
      return greaterThanOrEqual(op1, int64.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(long op1, BaseDataType op2)
   {
      return greaterThanOrEqual(new int64(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static boolean _isGreaterThanOrEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return (op1 >= op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(BaseDataType op1, double op2)
   {
      return greaterThanOrEqual(op1, new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isGreaterThanOrEqual(double op1, BaseDataType op2)
   {
      return greaterThanOrEqual(new decimal(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static boolean _isGreaterThanOrEqual(double op1, double op2)
   {
      // also handles double >= int and int >= double cases
      return greaterThanOrEqual(new decimal(op1), new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand OR if both operands are
    *           <code>unknown</code>.  <code>false</code> if the left operand
    *           is less than the right operand.  <code>unknown</code>
    *           when any one operand is <code>unknown</code> and the other
    *           is not.
    */
   public static logical isGreaterThanOrEqual(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 && u2) 
         return logical.of(true);
      
      if (u1 || u2)
         return logical.UNKNOWN;
      
      return logical.of(op1.compareTo(op2) >= 0);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the left operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(BaseDataType op1, boolean op2)
   {
      return isGreaterThanOrEqual(op1, logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the right operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(boolean op1, BaseDataType op2)
   {
      return isGreaterThanOrEqual(logical.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static logical isGreaterThanOrEqual(boolean op1, boolean op2)
   {
      return isGreaterThanOrEqual(logical.of(op1), logical.of(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the left operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(BaseDataType op1, String op2)
   {
      return isGreaterThanOrEqual(op1, new character(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the right operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(String op1, BaseDataType op2)
   {
      return isGreaterThanOrEqual(new character(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static logical isGreaterThanOrEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return logical.of(result >= 0);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the left operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(BaseDataType op1, long op2)
   {
      return isGreaterThanOrEqual(op1, new int64(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the right operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(long op1, BaseDataType op2)
   {
      return isGreaterThanOrEqual(new int64(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static logical isGreaterThanOrEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 >= op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the left operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(BaseDataType op1, double op2)
   {
      return isGreaterThanOrEqual(op1, new decimal(op2));
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.  <code>unknown</code>
    *           when the right operand is <code>unknown</code>.
    */
   public static logical isGreaterThanOrEqual(double op1, BaseDataType op2)
   {
      return isGreaterThanOrEqual(new decimal(op1), op2);
   }
      
   /**
    * Determines if the left operand is greater than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is greater than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is less than the right operand.
    */
   public static logical isGreaterThanOrEqual(double op1, double op2)
   {
      // also handles double >= int and int >= double cases
      return isGreaterThanOrEqual(new decimal(op1), new decimal(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the first operand is less than the
    *           second operand.  <code>false</code> if the first operand
    *           is equal to or greater than the second operand OR when
    *           either or both operands are <code>unknown</code>.
    */
   public static boolean lessThan(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 || u2)
         return false;
            
      return (op1.compareTo(op2) < 0);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand OR if both
    *           operands are <code>unknown</code>.  <code>unknown</code>
    *           when any one operand is <code>unknown</code> and the other
    *           is not.
    */
   public static boolean _isLessThan(BaseDataType op1, BaseDataType op2)
   {
      return lessThan(op1, op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           right operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(boolean op1, BaseDataType op2)
   {
      return lessThan(logical.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           left operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(BaseDataType op1, boolean op2)
   {
      return lessThan(op1, logical.of(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static boolean _isLessThan(boolean op1, boolean op2)
   {
      return lessThan(logical.of(op1), logical.of(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           right operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(String op1, BaseDataType op2)
   {
      return lessThan(new character(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           left operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(BaseDataType op1, String op2)
   {
      return lessThan(op1, new character(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static boolean _isLessThan(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return (result < 0);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           right operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(long op1, BaseDataType op2)
   {
      return lessThan(int64.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           left operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(BaseDataType op1, long op2)
   {
      return lessThan(op1, int64.of(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static boolean _isLessThan(long op1, long op2)
   {
      // INLINED for efficiency...
      return (op1 < op2);
   }
   
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           right operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(double op1, BaseDataType op2)
   {
      return lessThan(new decimal(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand or when the
    *           left operand is <code>unknown</code>.
    */
   public static boolean _isLessThan(BaseDataType op1, double op2)
   {
      return lessThan(op1, new decimal(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static boolean _isLessThan(double op1, double op2)
   {
      // also handles the double < int and int < double cases
      return lessThan(new decimal(op1), new decimal(op2));
   }
   
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand OR if both
    *           operands are <code>unknown</code>.  <code>unknown</code>
    *           when any one operand is <code>unknown</code> and the other
    *           is not.
    */
   public static logical isLessThan(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 && u2) 
         return logical.of(false);
      
      if (u1 || u2)
         return logical.UNKNOWN;
            
      return logical.of(op1.compareTo(op2) < 0);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the right operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(boolean op1, BaseDataType op2)
   {
      return isLessThan(logical.of(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the left operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(BaseDataType op1, boolean op2)
   {
      return isLessThan(op1, logical.of(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static logical isLessThan(boolean op1, boolean op2)
   {
      return isLessThan(logical.of(op1), logical.of(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the right operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(String op1, BaseDataType op2)
   {
      return isLessThan(new character(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the left operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(BaseDataType op1, String op2)
   {
      return isLessThan(op1, new character(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static logical isLessThan(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return logical.of(result < 0);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the right operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(long op1, BaseDataType op2)
   {
      return isLessThan(new int64(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the left operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(BaseDataType op1, long op2)
   {
      return isLessThan(op1, int64.of(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static logical isLessThan(long op1, long op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 < op2);
   }
   
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the right operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(double op1, BaseDataType op2)
   {
      return isLessThan(new decimal(op1), op2);
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    *           <code>unknown</code> when the left operand is 
    *           <code>unknown</code>.
    */
   public static logical isLessThan(BaseDataType op1, double op2)
   {
      return isLessThan(op1, new decimal(op2));
   }
      
   /**
    * Determines if the left operand is less than the right operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than the
    *           right operand. <code>false</code> if the left operand
    *           is greater than or equal to the right operand.
    */
   public static logical isLessThan(double op1, double op2)
   {
      // also handles the double < int and int < double cases
      return isLessThan(new decimal(op1), new decimal(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand OR if both operands are
    *           <code>unknown</code>.  <code>false</code> if the left operand
    *           is greater than the right operand OR when any one operand is
    *           <code>unknown</code> and the other is not.
    */
   public static boolean lessThanOrEqual(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 && u2) 
         return true;
      
      if (u1 || u2)
         return false;
            
      return (op1.compareTo(op2) <= 0);
   }
      
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand OR if both operands are
    *           <code>unknown</code>.  <code>false</code> if the left operand
    *           is greater than the right operand or when one (but not both)
    *           operands are <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(BaseDataType op1, BaseDataType op2)
   {
      return lessThanOrEqual(op1, op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(boolean op1, BaseDataType op2)
   {
      return lessThanOrEqual(logical.of(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(BaseDataType op1, boolean op2)
   {
      return lessThanOrEqual(op1, logical.of(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static boolean _isLessThanOrEqual(boolean op1, boolean op2)
   {
      return lessThanOrEqual(logical.of(op1), logical.of(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(String op1, BaseDataType op2)
   {
      return lessThanOrEqual(new character(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(BaseDataType op1, String op2)
   {
      return lessThanOrEqual(op1, new character(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static boolean _isLessThanOrEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return (result <= 0);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(long op1, BaseDataType op2)
   {
      return lessThanOrEqual(new int64(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(BaseDataType op1, long op2)
   {
      return lessThanOrEqual(op1, int64.of(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static boolean _isLessThanOrEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return (op1 <= op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the right
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(double op1, BaseDataType op2)
   {
      return lessThanOrEqual(new decimal(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand or when the left
    *           operand is <code>unknown</code>.
    */
   public static boolean _isLessThanOrEqual(BaseDataType op1, double op2)
   {
      return lessThanOrEqual(op1, new decimal(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static boolean _isLessThanOrEqual(double op1, double op2)
   {
      // also handles double <= int and int <= double
      return lessThanOrEqual(new decimal(op1), new decimal(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand OR if both operands are
    *           <code>unknown</code>.  <code>false</code> if the left operand
    *           is greater than the right operand.  <code>unknown</code>
    *           when any one operand is <code>unknown</code> and the other
    *           is not.
    */
   public static logical isLessThanOrEqual(BaseDataType op1, BaseDataType op2)
   {
      boolean u1 = op1.isUnknown();
      boolean u2 = op2.isUnknown(); 
      
      if (u1 && u2) 
         return logical.of(true);
      
      if (u1 || u2)
         return logical.UNKNOWN;
      
      return logical.of(op1.compareTo(op2) <= 0);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(boolean op1, BaseDataType op2)
   {
      return isLessThanOrEqual(logical.of(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(BaseDataType op1, boolean op2)
   {
      return isLessThanOrEqual(op1, logical.of(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static logical isLessThanOrEqual(boolean op1, boolean op2)
   {
      return isLessThanOrEqual(logical.of(op1), logical.of(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(String op1, BaseDataType op2)
   {
      return isLessThanOrEqual(new character(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(BaseDataType op1, String op2)
   {
      return isLessThanOrEqual(op1, new character(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static logical isLessThanOrEqual(String op1, String op2)
   {
      // INLINED for efficiency...
      
      // DO NOT use String.compareToIgnoreCase() since this lowercases
      // and yields different results for >, <, >= and <= forms when
      // [ \ ^ _ ' characters are included in the operands
      int result = op1.toUpperCase().compareTo(op2.toUpperCase());
      
      return logical.of(result <= 0);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(long op1, BaseDataType op2)
   {
      return isLessThanOrEqual(int64.of(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(BaseDataType op1, long op2)
   {
      return isLessThanOrEqual(op1, int64.of(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static logical isLessThanOrEqual(long op1, long op2)
   {
      // INLINED for efficiency...
      return logical.of(op1 <= op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the right operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(double op1, BaseDataType op2)
   {
      return isLessThanOrEqual(new decimal(op1), op2);
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.  
    *           <code>unknown</code> when the left operand is
    *           <code>unknown</code>.
    */
   public static logical isLessThanOrEqual(BaseDataType op1, double op2)
   {
      return isLessThanOrEqual(op1, new decimal(op2));
   }
   
   /**
    * Determines if the left operand is less than or equal to the right
    * operand.
    *
    * @param    op1
    *           The left operand.
    * @param    op2
    *           The right operand.
    *
    * @return   <code>true</code> if the left operand is less than or
    *           equal to the right operand.  <code>false</code> if the left
    *           operand is greater than the right operand.
    */
   public static logical isLessThanOrEqual(double op1, double op2)
   {
      // also handles double <= int and int <= double
      return isLessThanOrEqual(new decimal(op1), new decimal(op2));
   }
}