 
   conditional_upcase = [@letter_i]
 
-  for {codepoint, upper, _lower, _title} <- codes,
-      upper && upper != codepoint,
-      codepoint not in conditional_upcase do
+  {singles, tables} =
+    compute_lookup.(
+      for {codepoint, upper, _lower, _title} <- codes,
+          upper && upper != codepoint,
+          codepoint not in conditional_upcase,
+          do: {codepoint, upper}
+    )
+
+  for {codepoint, upper} <- singles do
     def upcase(<<unquote(codepoint), rest::bits>>, acc, mode) do
       upcase(rest, [unquote(upper) | acc], mode)
     end
   end
 
-  def upcase(<<char, rest::bits>>, acc, mode) do
-    upcase(rest, [char | acc], mode)
+  for {prefix, clauses} <- tables do
+    def upcase(<<unquote(prefix), byte, rest::bits>>, acc, mode) do
+      value = case byte, do: unquote(clauses)
+      upcase(rest, [value | acc], mode)
+    end
+  end
+
+  def upcase(<<byte, rest::bits>>, acc, mode) do
+    if byte >= ?a and byte <= ?z do
+      upcase(rest, [byte - 32 | acc], mode)
+    else
+      upcase(rest, [byte | acc], mode)
+    end
   end
 
   def upcase("", acc, _mode), do: IO.iodata_to_binary(:lists.reverse(acc))

        )
    end)

  # Sigma variants for Greek
  @letter_sigma <<0x03A3::utf8>>
  @letter_small_sigma_final <<0x03C2::utf8>>


  conditional_downcase = [@letter_I, @letter_I_dot_above, @letter_sigma]

  {singles, tables} =
    compute_lookup.(
      for {codepoint, _upper, lower, _title} <- codes,
          lower && lower != codepoint,
          codepoint not in conditional_downcase,
          do: {codepoint, lower}
    )

  for {codepoint, lower} <- singles do
    def downcase(<<unquote(codepoint), rest::bits>>, acc, mode) do
      downcase(rest, [unquote(lower) | acc], mode)
    end
  end

  for {prefix, clauses} <- tables do
    def downcase(<<unquote(prefix), byte, rest::bits>>, acc, mode) do
      value = case byte, do: unquote(clauses)
      downcase(rest, [value | acc], mode)
    end
  end

  def downcase(<<byte, rest::bits>>, acc, mode) do
    if byte >= ?A and byte <= ?Z do
      downcase(rest, [byte + 32 | acc], mode)
    else
      downcase(rest, [byte | acc], mode)
    end
  end

  def downcase("", acc, _mode), do: IO.iodata_to_binary(:lists.reverse(acc))
