I've got a macro in my OpenGL ES fragment shader that looks like this:
#define CHECK(x, DELTA, outColor, c1, c2) \
if (x < (delta + (DELTA))) { \
outColor = mix(c1, c2, smoothstep(delta, min(1.0, delta + (DELTA)), x)); \
x = 10.0; /*skip all subsequent CHECKs */ \
} \
delta += DELTA;
This works fine on my desktop, and on a variety of Android devices. (Yeah, I need to move away from the explicit flow control, but it gets the output I want for now.) The problem is that a few devices fail to compile this shader with errors like:
0:257: L0002: Undeclared variable 'DELTA'
,0:260: L0001: Expected literal or '(', got '\'
,0:263: L0001: Expected literal or '('...
(Line 257 is the "if ( x" line, line 260 is the "} \" line, and 263 is not shown here, its the first use of the CHECK macro. There are no other instances of all-caps "DELTA" elsewhere in the shader.)
I think this error means they're tripping up on the line-continuation characters? Is this really something that only some GLSL compilers support?
I'm building my shaders with #version 100 to be as compatible as possible between desktop and Android.
OpenGL
No
The v1.20.8 OpenGL GLSL spec says "No". Section 3.1 "Basis. Character Set" contains:
There is no line continuation character.
See: http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf or
http://www.opengl.org/registry/doc/GLSLangSpec.1.50.09.pdf
Well, yes
In a later version (v4.30.6) of the spec support for line-continuation characters was added. See:
http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf. I'm not clear when this was added.
Older "#version" directives like (#version 100) do not seem to disable line continuations (at least on my Nvidia desktop driver).
OpenGL ES
No, maybe
Section 1.5 "Compatibility" says:
Support of line continuation and support of UTF-8 characters within
comments is optional in GLSL ES 1.00 when used with the OpenGL ES 2.0
API. However, support is mandated for both of these when a GLSL ES
1.00 shader is used with the OpenGL ES 3.0 API.
See http://www.khronos.org/registry/gles/specs/3.0/GLSL_ES_Specification_3.00.3.pdf
Summary
Newer GLSL specifications include support for line continuation characters, but in practice this support is not disabled for explicitly versioned shaders. Older GLSL compilers may not support line continuation characters, so for maximum compatibility they should be avoided.
Related
This is probably a rather basic question, but I'm having a bit of trouble figuring it out, and it might be useful for future visitors.
I want to get at the raw data inside a PDF file, and I've managed to decode a page using the Python library PyPDF2 with the following commands:
import PyPDF2
with open('My PDF.pdf', 'rb') as infile:
mypdf = PyPDF2.PdfFileReader(infile)
raw_data = mypdf.getPage(1).getContents().getData()
print(raw_data)
Looking at the raw data provided, I have began to suspect that ASCII characters preceding carriage returns are significant: every carriage return that I've seen is preceded with one. It seems like they might be some kind of token identifier. I've already figured out that /RelativeColorimetric is associated with the sequence ri\r. I'm currently looking through the PDF 1.7 standard Adobe provides, and I know an explanation is in there somewhere, but I haven't been able to find it yet in that 756 page behemoth of a document
The defining thing here is not that \r – it is just inserted instead of a regular space for readability – but the fact that ri is an operator.
A PDF content stream uses a stack based Polish notation syntax: value1 value2 ... valuen operator
The full syntax of your ri, for example, is explained in Table 57 on p.127:
intent ri (PDF 1.1) Set the colour rendering intent in the graphics state (see 8.6.5.8, "Rendering Intents").
and the idea is that this indeed appears in this order inside a content stream. (... I tried to find an appropriate example of your ri in use but cannot find one; not even any in the ISO PDF itself that you referred to.)
A random stream snippet from elsewhere:
q
/CS0 cs
1 1 1 scn
1.5 i
/GS1 gs
0 -85.0500031 -14.7640076 0 287.0200043 344.026001 cm
BX
/Sh0 sh
EX
Q
(the indentation comes courtesy of my own PDF reader) shows operands (/CS0, 1 1 1, 1.5 etc.), with the operators (cs, scn, i etc.) at the end of each line for clarity.
This is explained in 7.8.2 Content Streams:
...
A content stream, after decoding with any specified filters, shall be interpreted according to the PDF syntax rules described in 7.2, "Lexical Conventions." It consists of PDF objects denoting operands and operators. The operands needed by an operator shall precede it in the stream. See EXAMPLE 4 in 7.4, "Filters," for an example of a content stream.
(my emphasis)
7.2.2 Character Set specifies that inside a content stream, whitespace characters such as tab, newline, and carriage return, are just that: separators, and may occur anywhere and in any number (>= 1) between operands and operators. It mentions
NOTE The examples in this standard use a convention that arranges tokens into lines. However, the examples’ use of white space for indentation is purely for clarity of exposition and need not be included in practical use.
– to which I can add that most PDF creating software indeed attempts to delimit 'lines' consisting of an operands-operator sequence with returns.
How to write strings (&str and String) containing newlines to text files?
In C you can switch between writing text as is or converting '\n' to proper end of line symbol for the OS via fopen flags, "w" or "wb". For example in Windows '\n' is converted to "\r\n" during I/O.
How can I achieve this with Rust? I cannot find corresponding API in std::fs::File.
There is no such API in the standard library (there might be a crate for this, though). The simplest way to write lines to a file is with the writeln! macro and it only uses \n for newlines.
It was probably considered (by the Rust developers) not useful enough because I'm pretty sure that nowadays \r\n is used only for Microsoft Notepad compatibility.
There once was an issue related to write not using CRLF on Windows, but it was concluded that:
the raw io::File will likely not handle it by default but would instead require a wrapper
(note: since Rust 1.0 it is no longer io::File, but fs::File)
Does anyone know if an underscore as format specifier (like %_f) does anything in C code?
I+ve found some code in a book that uses it, but I've googled and found nothing. I've also tested the following Objective-C code in Xcode and Xcode seems not to support this specifier. Is it valid in C?
-(void) print {
printf( "%_f + %_fi", real, imaginary );
}
Thanks!
The OS X man page for printf() says this:
An optional separator character ( , | ; | : | _ ) used for separating multiple values when printing an AltiVec or SSE vector,
or other multi-value unit.
NOTE: This is an extension to the printf() specification.
Behaviour of these values for printf() is only defined for operating
systems conforming to the AltiVec Technology Programming Interface
Manual. (At time of writing this includes only Mac OS X 10.2 and
later.)
I obtained the following code from Isabelle's wikipedia page:
theorem sqrt2_not_rational:
"sqrt (real 2) ∉ ℚ"
proof
assume "sqrt (real 2) ∈ ℚ"
then obtain m n :: nat where
n_nonzero: "n ≠ 0" and sqrt_rat: "¦sqrt (real 2)¦ = real m / real n"
and lowest_terms: "gcd m n = 1" ..
from n_nonzero and sqrt_rat have "real m = ¦sqrt (real 2)¦ * real n" by simp
then have "real (m²) = (sqrt (real 2))² * real (n²)" by (auto simp add: power2_eq_square)
also have "(sqrt (real 2))² = real 2" by simp
also have "... * real (m²) = real (2 * n²)" by simp
finally have eq: "m² = 2 * n²" ..
hence "2 dvd m²" ..
with two_is_prime have dvd_m: "2 dvd m" by (rule prime_dvd_power_two)
then obtain k where "m = 2 * k" ..
with eq have "2 * n² = 2² * k²" by (auto simp add: power2_eq_square mult_ac)
hence "n² = 2 * k²" by simp
hence "2 dvd n²" ..
with two_is_prime have "2 dvd n" by (rule prime_dvd_power_two)
with dvd_m have "2 dvd gcd m n" by (rule gcd_greatest)
with lowest_terms have "2 dvd 1" by simp
thus False by arith
qed
However, when I copy this text into an Isabelle instance, there are multiple 'do not enter' symbols to the left of each line. One says 'Illegal application of command "theorem" at top level' so I assumed that you cannot simply define a theorem at the top level and the wikipedia page was not supplying a complete initial example. I wrapped the theorem in a theory as follows:
theory Scratch
imports Main
begin
(* Theorem *)
end
Isabelle stopped complaining about the theorem, but, on the second line of the theorem, it now says:
Inner lexical error at: ℚ
Failed to parse proposition
It is also complaining about the proof line:
Illegal application of command "proof" in theory mode
It also has an error for the remaining lines in the theorem.
What is the proper way to wrap this theorem provided by wikipedia so that it can be checked in Isabelle?
I completely agree to Manuel, that just importing Main is not sufficient. If you're not interested in proofs, but just on testing irrationality then a good possibility would be to include $AFP/Real_Impl/Real_Impl from the Archive of Formal Proofs: then testing irrationality becomes very easy:
theory Test
imports "$AFP/Real_Impl/Real_Impl"
begin
lemma "sqrt 2 ∉ ℚ" by eval
lemma "sqrt 1.21 ∈ ℚ" by eval
lemma "sqrt 3.45 ∉ ℚ" by eval
end
Your guess that you have to wrap the “theorem” command in a theory in the way you did is correct. However, you need a few more imports, imports Main does not even load the theories containing sqrt, rational numbers, and prime numbers.
Moreover, the proof on Wikipedia is somewhat outdated. Isabelle is a very dynamic system; its maintainers port all the proofs in the library and the Archive of Formal Proofs with every release, but code snippets lying around somewhere (e.g. Wikipedia) tend to become outdated after a while, and I think this particular one is positively ancient.
For an up-to-date proof of pretty much the same thing, properly embedded in a theory with the right imports, look here:
http://isabelle.in.tum.de/repos/isabelle/file/4546c9fdd8a7/src/HOL/ex/Sqrt.thy
Note that this is for the development version of Isabelle; it may not work with your version. In any case, you should have the same file in the correct version as src/HOL/ex/Sqrt.thy in your downloaded Isabelle distribution.
Probably you encountered some encoding difficulties - this was the problem in my case (I got the same error).
Isabelle uses so called 'Isabelle symbols' to represent unicode characters (see three
(reference manual)[http://isabelle.in.tum.de/doc/isar-ref.pdf] from page 307).
If you use the jEdit IDE that gets distributed with Isabelle 2014 then --> looks the same as the \<longrightarrow> (the Isabelle symbol). The first cannot be parsed, the second is correct. If you copy and pasted the wiki-code this is the reason why it broke.
You can also take a look at the examples in <yourIsabelleInstallFolder/src/HOL/Isar_Examples.thy for further use of the isabelle symbols and the general structure of proofs written in the Isar language.
In my Objective-C code for my GPUImage framework, I have the following macro:
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define SHADER_STRING(text) # STRINGIZE2(text)
which allows me to inline multiline vertex and fragment shaders as NSString literals within my custom filter subclasses, like this:
NSString *const kGPUImagePassthroughFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
}
);
GPUImage needs this in order to provide formatted vertex and fragment shaders that are included in the body text of filter subclasses. Shipping them as separate files would make the framework unable to be compiled into a static library. Using the above macro, I can make these shaders able to be copied and pasted between the framework code and external shader files without a ridiculous amount of reformatting work.
Swift does away with compiler macros, and the documentation has this to say:
Complex macros are used in C and Objective-C but have no counterpart
in Swift. Complex macros are macros that do not define constants,
including parenthesized, function-like macros. You use complex macros
in C and Objective-C to avoid type-checking constraints or to avoid
retyping large amounts of boilerplate code. However, macros can make
debugging and refactoring difficult. In Swift, you can use functions
and generics to achieve the same results without any compromises.
Therefore, the complex macros that are in C and Objective-C source
files are not made available to your Swift code.
Per the line "In Swift, you can use functions and generics to achieve the same results without any compromises", is there a way in Swift to provide multiline string literals without resorting to a string of concatenation operations?
Alas Swift multiline strings are still not available, as far as I know. However when doing some research regarding this, I found a workaround which could be useful. It is a combination of these items:
A Quick Hack to Quote Swift Strings in a Playground - Describing how to make an service replacing and fixing texts
The comment by pyrtsa, regarding using "\n".join(...) to emulate the multiline strings
Setup an automated service
Using Automator you could set up an extra service with the following properties:
A single action of "Run Shell Script"
Tick off the "Output replaces selected text"
Change shell to /usr/bin/perl
Add the code excerpt below to the action window
Save as something like "Replace with quoted swift multiline join"
Code excerpt
print "\"\\n\".join([\n"; # Start a join operation
# For each line, reformat and print
while(<>) {
print " "; # A little indentation
chomp; # Loose the newline
s/([\\\"])/\\$1/g; # Replace \ and " with escaped variants
print "\"$_\""; # Add quotes around the line
print "," unless eof # Add a comma, unless it is the last line
print "\n"; # End the line, preserving original line count
}
print " ])"; # Close the join operation
You are of course free to use whatever shell and code you want, I chose perl as that is familiar to me, and here are some comments:
I used the "\n".join(...) version to create the multiline string, you could use the extension answer from Swift - Split string over multiple lines, or even the + variant, I'll leave that as an exercise for the user
I opted for a little indentation with spaces, and to replace the \ and " to make it a little sturdier
Comments are of course optional, and you could probably shorten the code somewhat. I tried to opt for clarity and readability
The code, as is, preserves spaces, but you could be edited if that is not wanted. Also left as an exercise for the user
Usage of service
Open up your playground or code editor, and insert/write some multline text:
Mark the text block
Execute Xcode (or similar) > Services > Replace with quoted swift multiline join
You now have a multiline string in proper swift coding. Here are an example of before and after text:
Here is my multiline text
example with both a " and
a \ within the text
"\n".join([
"Here is my multiline text ",
"example with both a \" and",
"a \\ within the text"
])
It looks like your end goal is to avoid including standalone shader files?
If so one technique would be to write a quick command line utility that generates a .swift file of string constants representing the shader functions in a certain folder.
Include the resulting .swift file in your project and you have no runtime penalty, and even easier debugging if you generate the code nicely.
Would probably take less than an hour, never need macros again for shaders.