content: # Copyright 2015 Google Inc. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  import struct, itertools
  
  from ..jvmops import *
  from ...util import s32
  
  # Create a precomputed lookup table giving the bytecode sequence to generate
  # any primative constant of 3 bytes or less plus special float values (negative
  # infinity requires 4 bytes but is included anyway to simplify things elsewhere)
  #
  # For example
  # 128 -> sipush 128
  # -65535 -> iconst_m1 i2c ineg
  # 2147483647 -> iconst_m1 iconst_m1 iushr
  # 1L -> lconst_1
  # 127L -> bipush 127 i2l
  # 42.0f -> bipush 42 i2f
  # -Inf -> dconst_1 dneg dconst_0 ddiv
  #
  # Lookup table keys are s32/s64 for ints/longs and u32/u64 for floats/doubles
  # There are multiple NaN representations, so we normalize NaNs to the
  # representation of all 1s (e.g. float NaN = 0xFFFFFFFF)
  
  def u32(x): return x % (1<<32)
  def u64(x): return x % (1<<64)
  
  FLOAT_SIGN = 1<<31
  FLOAT_NAN = u32(-1)
  FLOAT_INF = 0xFF << 23
  FLOAT_NINF = FLOAT_INF ^ FLOAT_SIGN
  def i2f(x):
      if x == 0:
          return 0
      if x < 0:
          return i2f(-x) ^ FLOAT_SIGN
      shift = 24 - x.bit_length()
      # Don't bother implementing rounding since we'll only convert small ints
      # that can be exactly represented anyway
      assert shift >= 0
      mantissa = x << shift
      exponent = shift + 127
      return (exponent << 23) | mantissa
  
  DOUBLE_SIGN = 1<<63
  DOUBLE_NAN = u64(-1)
  DOUBLE_INF = 0x7FF << 52
  DOUBLE_NINF = DOUBLE_INF ^ DOUBLE_SIGN
  def i2d(x):
      if x == 0:
          return 0
      if x < 0:
          return i2d(-x) ^ DOUBLE_SIGN
      shift = 53 - x.bit_length()
      assert shift >= 0
      mantissa = x << shift
      exponent = shift + 1023
      return (exponent << 52) | mantissa
  
  # add if value is shorter then current best
  def add(d, k, v):
      if k not in d or len(v) < len(d[k]):
          d[k] = v
  
  if __name__ == "__main__":
      # int constants
      all_ints = {}
  
      # 1 byte ints
      for i in range(-1, 6):
          add(all_ints, i, bytes([ICONST_0 + i]))
      # Sort for determinism. Otherwise -0x80000000 could be either
      # 1 << -1 or -1 << -1, for example
      int_1s = sorted({k for k,v in all_ints.items() if len(v) == 1})
  
      # 2 byte ints
      for i in range(-128, 128):
          add(all_ints, i, struct.pack('>Bb', BIPUSH, i))
      for i in int_1s:
          add(all_ints, i % 65536, all_ints[i] + bytes([I2C]))
      int_2s = sorted({k for k,v in all_ints.items() if len(v) == 2})
  
      # 3 byte ints
      for i in range(-32768, 32768):
          add(all_ints, i, struct.pack('>Bh', SIPUSH, i))
      for i in int_2s:
          add(all_ints, i % 65536, all_ints[i] + bytes([I2C]))
          add(all_ints, s32(-i), all_ints[i] + bytes([INEG]))
      for x, y in itertools.product(int_1s, int_1s):
          add(all_ints, s32(x << (y % 32)), all_ints[x] + all_ints[y] + bytes([ISHL]))
          add(all_ints, s32(x >> (y % 32)), all_ints[x] + all_ints[y] + bytes([ISHR]))
          add(all_ints, s32(u32(x) >> (y % 32)), all_ints[x] + all_ints[y] + bytes([IUSHR]))
  
      # long constants
      all_longs = {}
      for i in range(0, 2):
          add(all_longs, i, bytes([LCONST_0 + i]))
  
      for i in int_1s + int_2s:
          add(all_longs, i, all_ints[i] + bytes([I2L]))
  
      # float constants
      all_floats = {}
      for i in range(0, 2):
          add(all_floats, i2f(i), bytes([FCONST_0 + i]))
  
      for i in int_1s + int_2s:
          add(all_floats, i2f(i), all_ints[i] + bytes([I2F]))
  
      # hardcode unusual float values for simplicity
      add(all_floats, FLOAT_SIGN, bytes([FCONST_0, FNEG])) # -0.0
      add(all_floats, FLOAT_NAN, bytes([FCONST_0, FCONST_0, FDIV])) # NaN
      add(all_floats, FLOAT_INF, bytes([FCONST_1, FCONST_0, FDIV])) # Inf
      add(all_floats, FLOAT_NINF, bytes([FCONST_1, FNEG, FCONST_0, FDIV])) # -Inf
  
      # double constants
      all_doubles = {}
      for i in range(0, 2):
          add(all_doubles, i2d(i), bytes([DCONST_0 + i]))
  
      for i in int_1s + int_2s:
          add(all_doubles, i2d(i), all_ints[i] + bytes([I2D]))
  
      add(all_doubles, DOUBLE_SIGN, bytes([DCONST_0, DNEG])) # -0.0
      add(all_doubles, DOUBLE_NAN, bytes([DCONST_0, DCONST_0, DDIV])) # NaN
      add(all_doubles, DOUBLE_INF, bytes([DCONST_1, DCONST_0, DDIV])) # Inf
      add(all_doubles, DOUBLE_NINF, bytes([DCONST_1, DNEG, DCONST_0, DDIV])) # -Inf
  
      print('''
  # Copyright 2015 Google Inc. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  # Autogenerated by genlookup.py - do not edit''')
  
      for name, d in zip('INTS LONGS FLOATS DOUBLES'.split(), [all_ints, all_longs, all_floats, all_doubles]):
          print(name + ' = {')
          for k, v in sorted(d.items()):
              print('    {}: {},'.format(hex(k), v))
          print('}')