Date   

new Imath repo

Cary Phillips
 

We had an unexpected delay in getting the ASWF Imath repo created, but it's in place now:


Thanks to Owen, it preserves the proper file revision history, and it builds, too. There's also a separate repo for PyImath: https://github.com/AcademySoftwareFoundation/pyimath.

I set up a GitHub project to track progress using GitHub Issues.  If you're interested in contributing to the discussion about further developments with Imath, please subscribe to notifications from the GitHub repo, and comment freely on the issues or file new ones as you think of things you'd like to discuss or propose.

Thanks,
- Cary

--
Cary Phillips | R&D Supervisor | ILM | San Francisco


OpenEXR v2.5.2 and v2.4.2 released

Cary Phillips
 

OpenEXR v2.5.2 and v2.4.2 have been released and are available for download at https://github.com/AcademySoftwareFoundation/openexr/releases.

OpenEXR v2.5.2 is a patch release with various bug/security and build/install fixes:
  • Invalid input could cause a heap-use-after-free error in DeepScanLineInputFile::DeepScanLineInputFile()
  • Invalid chunkCount attributes could cause heap buffer overflow in getChunkOffsetTableSize()
  • Invalid tiled input file could cause invalid memory access TiledInputFile::TiledInputFile()
  • OpenEXRConfig.h now correctly sets OPENEXR_PACKAGE_STRING to "OpenEXR" (rather than "IlmBase")
  • Various Windows build fixes
OpenEXR v2.4.2 is also a patch release that backports the bug fixes to v2.4:
  • Invalid input could cause a heap-use-after-free error in DeepScanLineInputFile::DeepScanLineInputFile()
  • Invalid chunkCount attributes could cause heap buffer overflow in getChunkOffsetTableSize()
  • Invalid tiled input file could cause invalid memory access TiledInputFile::TiledInputFile()
  • OpenEXRConfig.h now correctly sets OPENEXR_PACKAGE_STRING to "OpenEXR" (rather than "IlmBase")

--
Cary Phillips | R&D Supervisor | ILM | San Francisco


Re: Imath: Options for Exceptions

Kimball Thurston
 

Wow, you guys already had a healthy discussion and I haven't even had coffee yet.

What I had been think about was I think similar in some ways to all of these, yet perhaps a bit different / expanded, so I'll write it here as a mostly separate option. This has come up in a BoF or on the discussion list or somewhere before, but I was thinking it might be worth enabling the library to be a bit more flexible in it's representation at the same time we deal with the exceptions. This is in some ways conflating separate discussions, but imagine:


This allows us to have compile time switching of the storage to a simd type, as well as enabling / disabling the exceptions. Obviously there are all manner of conversion operators and such missing, and probably need to iterate on some of this and have some things like type traits to handle the ability to expand the type (i.e. float + float -> double if you want), and some other fiddly bits, but hopefully this gives a good flavor.

I do realize this changes the API, in that we would have to lose the storage option I wrote up to preserve v.x instead of v.x(), which is perhaps a portability issue. Although we might be able to handle that by rejiggering a bit to roll the storage down a level for the default type. Actually, that is probably a good idea to preserve the API behavior. meh, too lazy, we can do that if we like the idea.

However, the nugget of what I suggest is that it does allow you to have both types alive in the program at once, one throwing an exception, one not. And you can have a third or fourth "stack version" of vector that is implemented using simd, but leave the other as a tightly-packed / castable version that can be you big array of vertices on the heap, as they are simply multiple types. And I'd have to think about how to fix my above code, but we could also easily have in-place rebinding / conversion operations to treat one as another type.

Some places have patterns like normalize and normalizeExc (in the case of vector), while others have this function(bool doThrow) semantics. It seems like if we're cleaning things up, adding const / constexpr / whatever other c++11 cleanup, it might be worth cleaning up the API to be consistent, and I would argue that having separate types is the best way to do this rather than any compile time switch or separate functions. We can debate what the default type should be for V3f, although I would argue for the noexcept case.

So if the storage and math impl stuff is too much to swallow and this stuff should just stay dead simple, I can be convinced of that, although we could do a subset of that which is just the error handling, which I think is exactly what Nick and others are suggesting - just make the exception / no exception stuff a separate typed object, burdening the type system, and not the API.

K



On Fri, Jun 12, 2020 at 5:44 PM Nick Porcino <nick.porcino@...> wrote:
Thanks Owen!

I'm going to take an opinion here, attempting to take into account the foregoing discussion, and introducing my own biases and prejudices:

As Larry points out, option 1 isn't suitable as it does not allow elision of the throwing code.

Option 2 is necessary, because as Peter points out, our ideal case per our current thinking, is that existing code continues to compile without modification.

I prefer that we introduce unambiguous result codes. Not fancy modern C++ result codes, but straight forward comparable values lacking exotic semantics. I further suggest that we do not muddy things by contriving an Imath uber set of codes designed to capture all possible exceptional values, but rather we target results strictly and specifically. If an invert operation can succeed due to the matrix being invertible, or fail due to being singular, then we restrict the possible codes unambiguously:

enum class InvertResultCode { Invertible, Singular };

Next, we do not supply a return by reference in the new functions, but only an InvertResultCode in the case of an in place inversion, or an InvertResult in the const versions. The InvertResult is scoped to the class. This approach is similar to Matt's drive by suggestion, except that the value in the InvertResult is not guarded by a code affordance, just common sense. If the result is InvertResultCode is singular, I think we should simply memcpy the matrix into the result, because we should not leave the door open to UB due to uninitialized memory. std::optional should not be considered in this case, as it can throw exceptions, and has a number of other well documented overheads, as Thiago points out.

@@ -920,6 +935,19 @@ template <class T> class Matrix44
 
     Matrix44<T>         gjInverse (bool singExc = false) const;
 
+    // if code is Singular, result will be a copy of the matrix
+    struct InvertResult { InvertResultCode code, Matrix44 result };
+
+    // if the matrix is singular, no modification is made
+    InvertResultCode    invert () noexcept;
+
+    InvertResult        inverse () const noexcept;
+
+    // if the matrix is singular, no modification is made
+    InvertResultCode    gjInvert () noexcept;
+
+    InvertResult        gjInverse () const noexcept;
 
     //------------------------------------------------
     // Calculate the matrix minor of the (r,c) element

On Larry's reference of Kimball's suggestion, or was it mine? of an error handling policy object, I recommend we do not do that. I was a proponent of that approach for a long time, but my experience since then has been that it imposes an unnecessary level of genericity where it is more or less not warranted. As Larry speculates for the filesystem pattern, I found that a policy template trait litters and clutters the code with accommodations to its needs. 

To Larry's point 5 on a preprocessor symbol, I believe we should be invoking an option in the cmake file, and emitting the symbol in the ImathConfig.h file. I advocate a straight ifndef to guard the exception throwing code, as opposed to #if as I personally find #ifndef to be less error prone. I am flexible on this point.

Peter, you say - 

> Ideally, the solution should support libraries that want to compile against Imath, where those libraries want to offer the choice of throwing and no-throwing versions. 

Yes, I agree. You then say -

> Differently named functions would make that tedious, as would a compile-time preprocessor flag in Imath.

I respectfully disagree. I think that it is best to be explicit, where an API always behaves as defined, and does not have hidden behavioral changes due to compilation choices. That means, in my mind, that differently named functions are not tedious, but explicit, and allow me to express my intent in the code explicitly. You then go on to say,

>  It may also be that folks want exception handling on for a debug build only, and turn them off for an optimized release.

A combination of a preprocessor guard, and explicit intentional naming of all variants, means that one may combine behaviors to your heart's content, however, the suggested scenario of throwing in debug, and not in release becomes admittedly tedious. I propose that behavior that differs in runtime between debug and release builds is not in general desirable, as it has already bit us in the test suite. I am therefore in favor of this scenario being in fact, tedious, as it will be an intentional choice in code, not a hidden choice in a makefile.

Your suggestion in the gist of a templated parameter to select throwing or non-throwing code is elegant, clean reading, and exactly expresses intent, all of which are points that strongly support. Unfortunately, I think we can't actually do that, first because it means existing code does have to change to accomodate the API, and second because Microsoft compilers do not deadstrip symbols or code when a templated class is instantiated and exported from a DLL. All methods are instantiated and code generated irrespective of whether the compiler can discover a usage of the method, so that would be contradiction to our desire to generate code that strictly has no exception code in it. Arguably, we may decide to state that Imath is a static library, but it does not sidestep the issue as the Imath types may be embedded in a user class that is exported from a shared library, and the can of worms then reappears.

As to whether it's a requirement that Imath run quickly, the answer is yes, it should. I was at some pains years ago to structure the algorithms in exrenvmap such that it executed in a reasonable amount of time. I would prefer that we don't regress on that front in general. There are a great many other math libraries much faster than Imath, but at the same time, one shouldn't have to hesitate to use Imath because of a worry that it is unreasonably slow. Vectorizing compilers mean that we often get good results with Imath due its simplicity. As anecdata, I rewrote some inner loops at Oculus Research from Eigen to a combination of direct simd code and Imath code and got great speedups because the Eigen template instantiation was too complex for the compiler to do anything with, whereas the Imath code exactly matched canonical patterns that the vectorizing optimizer looks for.

- Nick

On Thu, Jun 11, 2020 at 3:12 PM Larry Gritz <lg@...> wrote:
VFXPlatform 2021 is scheduled to be C++17.

While I can imagine some uses for exotic optional return types, I don't think that core math functions is where I'd want them to be.
I want my code using Imath to be as straight-line as possible, and my own preference is just to have "safe" versions where needed (as an example of what I mean, a "safe_sqrt" would clamp its input to minimum of 0 rather than have exceptions or error codes at all -- if somebody cares about identifying bad domain, they should check it before making the call).


On Jun 11, 2020, at 1:58 PM, Thiago Ize <thiago.ize@...> wrote:

std::optional, like most fancy c++ features, is neat on paper, and I'll probably find uses for it once I'm allowed to use C++17, but I get worried it'll still bring too much baggage. For instance, if you use the optional's value(), it'll cause the compiler to generate exception handling code (looking at the assembly I see a std::bad_optional_access can be thrown). If you use value_or() you can avoid the exceptions, which is nice, but you then need to supply the value to use when there's an error which can be either neat or annoying depending on the situation. Even when there's no error, both versions will never be as fast as code that does no error checking (not sure if that matters for imath).

For those curious in trying it out, here's my quick hack at implementing Matt's suggestion: https://gcc.godbolt.org/z/ZYFaap 

Also, the vfx reference platform for 2020 looks to be c++14 (no mention of what will be in 2021), so that might be another impediment even if this is the cleanest approach.

Thiago

On Thu, Jun 11, 2020 at 1:43 PM Matt Pharr <matt.pharr@...> wrote:
Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code, 
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz







--
Larry Gritz






--
--------------------------------
Nick Porcino @meshula
Virtual and augmented production, interactive applications, and robotics, since 1982


Re: Meeting today: Two Questions [Imath]

Nick Porcino
 

I second the motion earlier in the thread to not support autoconf for Imath.


On Thu, Jun 4, 2020 at 12:43 PM Larry Gritz <lg@...> wrote:
We can talk about this on the call, but... must we really bring Iex into Imath?

Does Imath really need exceptions outside standard C++ ones? (Keeping in mind that we can use 'using' to alias the old names to preserve source compatibility.)

Grep says only the following are thrown by Imath (eliminating duplicates):

ImathFrustum.h:        throw IEX_NAMESPACE::ArgExc ("fovx and fovy cannot both be non-zero.");
ImathFrustum.h:        throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: "
ImathMatrix.h:                throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix.");
ImathVec.h: throw NullVecExc ("Cannot normalize null vector.");
ImathVec.h:            throw InfPointExc ("Cannot normalize point at infinity.");
ImathGL.h: throw IEX_NAMESPACE::OverflowExc ("GL matrix overflow");
ImathMatrixAlgo.h: throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ("Cannot remove zero scaling "


These all look like they could be std::out_of_range, std::domain_error, std::overflow_error.


On Thu, Jun 4, 2020 at 11:44 AM Cary Phillips <cary@...> wrote:

Also, we're assuming we lose the term "IlmBase" entirely, and the current subfolders of IlmBase move to the top level of the new repo.  So, the "Imath" repo has subfolders called Imath, ImathTest, Half, HalfTest, Iex, IexMath, IexTest:

...

And IlmThread stays with openexr.

Just confirming, is this what others are expecting?



On Thu, Jun 4, 2020 at 9:09 AM Larry Gritz <lg@...> wrote:
My answers would be:

1. Let's please DON'T support autoconf any more

2. Yes, submodule!


On Jun 4, 2020, at 8:34 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

In today's meeting I want to get a sense of the group's impressions/concerns on two things:

1: Supporting Autoconf building in the new Imath repo (and consequentially OpenEXR as a whole)

    - i.e. is it still necessary or is cmake alone sufficient?

2: Using git submodules to manage Imath installation for OpenEXR

    - This permits: automatically cloning the source of Imath (if it's not detected) and otherwise building almost identically to how OpenEXR does already

    - Information about this can be found here

If there are any concerns I would like to hear them. I heir on the side of not supporting Autoconf, and using the submodules.

Owen Thompson

_

--
Larry Gritz






--
Cary Phillips | R&D Supervisor | ILM | San Francisco



--
Larry Gritz
lg@...



--
--------------------------------
Nick Porcino @meshula
Virtual and augmented production, interactive applications, and robotics, since 1982


Re: Imath: Options for Exceptions

Nick Porcino
 

Thanks Owen!

I'm going to take an opinion here, attempting to take into account the foregoing discussion, and introducing my own biases and prejudices:

As Larry points out, option 1 isn't suitable as it does not allow elision of the throwing code.

Option 2 is necessary, because as Peter points out, our ideal case per our current thinking, is that existing code continues to compile without modification.

I prefer that we introduce unambiguous result codes. Not fancy modern C++ result codes, but straight forward comparable values lacking exotic semantics. I further suggest that we do not muddy things by contriving an Imath uber set of codes designed to capture all possible exceptional values, but rather we target results strictly and specifically. If an invert operation can succeed due to the matrix being invertible, or fail due to being singular, then we restrict the possible codes unambiguously:

enum class InvertResultCode { Invertible, Singular };

Next, we do not supply a return by reference in the new functions, but only an InvertResultCode in the case of an in place inversion, or an InvertResult in the const versions. The InvertResult is scoped to the class. This approach is similar to Matt's drive by suggestion, except that the value in the InvertResult is not guarded by a code affordance, just common sense. If the result is InvertResultCode is singular, I think we should simply memcpy the matrix into the result, because we should not leave the door open to UB due to uninitialized memory. std::optional should not be considered in this case, as it can throw exceptions, and has a number of other well documented overheads, as Thiago points out.

@@ -920,6 +935,19 @@ template <class T> class Matrix44
 
     Matrix44<T>         gjInverse (bool singExc = false) const;
 
+    // if code is Singular, result will be a copy of the matrix
+    struct InvertResult { InvertResultCode code, Matrix44 result };
+
+    // if the matrix is singular, no modification is made
+    InvertResultCode    invert () noexcept;
+
+    InvertResult        inverse () const noexcept;
+
+    // if the matrix is singular, no modification is made
+    InvertResultCode    gjInvert () noexcept;
+
+    InvertResult        gjInverse () const noexcept;
 
     //------------------------------------------------
     // Calculate the matrix minor of the (r,c) element

On Larry's reference of Kimball's suggestion, or was it mine? of an error handling policy object, I recommend we do not do that. I was a proponent of that approach for a long time, but my experience since then has been that it imposes an unnecessary level of genericity where it is more or less not warranted. As Larry speculates for the filesystem pattern, I found that a policy template trait litters and clutters the code with accommodations to its needs. 

To Larry's point 5 on a preprocessor symbol, I believe we should be invoking an option in the cmake file, and emitting the symbol in the ImathConfig.h file. I advocate a straight ifndef to guard the exception throwing code, as opposed to #if as I personally find #ifndef to be less error prone. I am flexible on this point.

Peter, you say - 

> Ideally, the solution should support libraries that want to compile against Imath, where those libraries want to offer the choice of throwing and no-throwing versions. 

Yes, I agree. You then say -

> Differently named functions would make that tedious, as would a compile-time preprocessor flag in Imath.

I respectfully disagree. I think that it is best to be explicit, where an API always behaves as defined, and does not have hidden behavioral changes due to compilation choices. That means, in my mind, that differently named functions are not tedious, but explicit, and allow me to express my intent in the code explicitly. You then go on to say,

>  It may also be that folks want exception handling on for a debug build only, and turn them off for an optimized release.

A combination of a preprocessor guard, and explicit intentional naming of all variants, means that one may combine behaviors to your heart's content, however, the suggested scenario of throwing in debug, and not in release becomes admittedly tedious. I propose that behavior that differs in runtime between debug and release builds is not in general desirable, as it has already bit us in the test suite. I am therefore in favor of this scenario being in fact, tedious, as it will be an intentional choice in code, not a hidden choice in a makefile.

Your suggestion in the gist of a templated parameter to select throwing or non-throwing code is elegant, clean reading, and exactly expresses intent, all of which are points that strongly support. Unfortunately, I think we can't actually do that, first because it means existing code does have to change to accomodate the API, and second because Microsoft compilers do not deadstrip symbols or code when a templated class is instantiated and exported from a DLL. All methods are instantiated and code generated irrespective of whether the compiler can discover a usage of the method, so that would be contradiction to our desire to generate code that strictly has no exception code in it. Arguably, we may decide to state that Imath is a static library, but it does not sidestep the issue as the Imath types may be embedded in a user class that is exported from a shared library, and the can of worms then reappears.

As to whether it's a requirement that Imath run quickly, the answer is yes, it should. I was at some pains years ago to structure the algorithms in exrenvmap such that it executed in a reasonable amount of time. I would prefer that we don't regress on that front in general. There are a great many other math libraries much faster than Imath, but at the same time, one shouldn't have to hesitate to use Imath because of a worry that it is unreasonably slow. Vectorizing compilers mean that we often get good results with Imath due its simplicity. As anecdata, I rewrote some inner loops at Oculus Research from Eigen to a combination of direct simd code and Imath code and got great speedups because the Eigen template instantiation was too complex for the compiler to do anything with, whereas the Imath code exactly matched canonical patterns that the vectorizing optimizer looks for.

- Nick


On Thu, Jun 11, 2020 at 3:12 PM Larry Gritz <lg@...> wrote:
VFXPlatform 2021 is scheduled to be C++17.

While I can imagine some uses for exotic optional return types, I don't think that core math functions is where I'd want them to be.
I want my code using Imath to be as straight-line as possible, and my own preference is just to have "safe" versions where needed (as an example of what I mean, a "safe_sqrt" would clamp its input to minimum of 0 rather than have exceptions or error codes at all -- if somebody cares about identifying bad domain, they should check it before making the call).


On Jun 11, 2020, at 1:58 PM, Thiago Ize <thiago.ize@...> wrote:

std::optional, like most fancy c++ features, is neat on paper, and I'll probably find uses for it once I'm allowed to use C++17, but I get worried it'll still bring too much baggage. For instance, if you use the optional's value(), it'll cause the compiler to generate exception handling code (looking at the assembly I see a std::bad_optional_access can be thrown). If you use value_or() you can avoid the exceptions, which is nice, but you then need to supply the value to use when there's an error which can be either neat or annoying depending on the situation. Even when there's no error, both versions will never be as fast as code that does no error checking (not sure if that matters for imath).

For those curious in trying it out, here's my quick hack at implementing Matt's suggestion: https://gcc.godbolt.org/z/ZYFaap 

Also, the vfx reference platform for 2020 looks to be c++14 (no mention of what will be in 2021), so that might be another impediment even if this is the cleanest approach.

Thiago

On Thu, Jun 11, 2020 at 1:43 PM Matt Pharr <matt.pharr@...> wrote:
Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code, 
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz







--
Larry Gritz






--
--------------------------------
Nick Porcino @meshula
Virtual and augmented production, interactive applications, and robotics, since 1982


OpenEXR v2.5.2 and v2.4.2 on the way

Cary Phillips
 

We're planning new OpenEXR patch releases soon with miscellaneous minor bug/security fixes, most triggered by invalid input identified via fuzz tests, both for v2.5 and backported to v2.4.

- Cary

--
Cary Phillips | R&D Supervisor | ILM | San Francisco


Re: Imath: Options for Exceptions

Larry Gritz
 

VFXPlatform 2021 is scheduled to be C++17.

While I can imagine some uses for exotic optional return types, I don't think that core math functions is where I'd want them to be.
I want my code using Imath to be as straight-line as possible, and my own preference is just to have "safe" versions where needed (as an example of what I mean, a "safe_sqrt" would clamp its input to minimum of 0 rather than have exceptions or error codes at all -- if somebody cares about identifying bad domain, they should check it before making the call).


On Jun 11, 2020, at 1:58 PM, Thiago Ize <thiago.ize@...> wrote:

std::optional, like most fancy c++ features, is neat on paper, and I'll probably find uses for it once I'm allowed to use C++17, but I get worried it'll still bring too much baggage. For instance, if you use the optional's value(), it'll cause the compiler to generate exception handling code (looking at the assembly I see a std::bad_optional_access can be thrown). If you use value_or() you can avoid the exceptions, which is nice, but you then need to supply the value to use when there's an error which can be either neat or annoying depending on the situation. Even when there's no error, both versions will never be as fast as code that does no error checking (not sure if that matters for imath).

For those curious in trying it out, here's my quick hack at implementing Matt's suggestion: https://gcc.godbolt.org/z/ZYFaap 

Also, the vfx reference platform for 2020 looks to be c++14 (no mention of what will be in 2021), so that might be another impediment even if this is the cleanest approach.

Thiago

On Thu, Jun 11, 2020 at 1:43 PM Matt Pharr <matt.pharr@...> wrote:
Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code, 
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz







--
Larry Gritz





Re: Imath: Options for Exceptions

Peter Hillman
 


Ideally, existing code out there should compile without major modification and behave similarly to how it does now, which probably means IMath should be throwing exceptions by default and return types shouldn't change. Ideally, the solution should support libraries that want to compile against Imath, where those libraries want to offer the choice of throwing and no-throwing versions. Differently named functions would make that tedious, as would a compile-time preprocessor flag in Imath. It may also be that folks want exception handling on for a debug build only, and turn them off for an optimized release.

Perhaps the no-except versions of these functions should do very little error testing. The main reason for no-except versions is to avoid overhead, so maybe the test itself should be avoided. The no-except version of aspect() or normalize() might return infinity or NaN, and it's up to the caller to check for that, or sanitize the values up front for speed.
After all, it's as easy to check the result of aspect() for infinity/NaN as it would be to check an error object returned from aspect() and just as easy to forget to to do it too. Error checking in invert functions would still be required.

A variation on option #1 is to have overloaded functions that take a dummy parameter to indicate what the behavior should be, rather like type traits in STL.
You can pass an extra parameter to the function to make an explicit choice whether or not you want exceptions, but the type of that parameter controls the behavior, rather than its value. A single line change in user code can then turn exceptions on and off. Something along these lines: https://gist.github.com/peterhillman/b233c344918be066ad6704e378a71024


On 12/06/20 9:50 am, Matt Pharr wrote:
std::optional was admittedly a bad suggestion for a math library. Here’s an alternative where ResultOr just protects access to the value and asserts if you try to access it without checking the error code: https://gcc.godbolt.org/z/PEYKmx

If you do an apples-to-apples comparison where the error code is actually checked, then check() and check2() generate the same code. Amusingly, the assert() call in ResultOr::get() is optimized away because the calling code has checked the error code already.

Matt

On Jun 11, 2020, at 1:58 PM, Thiago Ize <thiago.ize@...> wrote:

std::optional, like most fancy c++ features, is neat on paper, and I'll probably find uses for it once I'm allowed to use C++17, but I get worried it'll still bring too much baggage. For instance, if you use the optional's value(), it'll cause the compiler to generate exception handling code (looking at the assembly I see a std::bad_optional_access can be thrown). If you use value_or() you can avoid the exceptions, which is nice, but you then need to supply the value to use when there's an error which can be either neat or annoying depending on the situation. Even when there's no error, both versions will never be as fast as code that does no error checking (not sure if that matters for imath).

For those curious in trying it out, here's my quick hack at implementing Matt's suggestion: https://gcc.godbolt.org/z/ZYFaap 

Also, the vfx reference platform for 2020 looks to be c++14 (no mention of what will be in 2021), so that might be another impediment even if this is the cleanest approach.

Thiago

On Thu, Jun 11, 2020 at 1:43 PM Matt Pharr <matt.pharr@...> wrote:
Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code, 
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz









Re: Imath: Options for Exceptions

Matt Pharr
 

std::optional was admittedly a bad suggestion for a math library. Here’s an alternative where ResultOr just protects access to the value and asserts if you try to access it without checking the error code: https://gcc.godbolt.org/z/PEYKmx

If you do an apples-to-apples comparison where the error code is actually checked, then check() and check2() generate the same code. Amusingly, the assert() call in ResultOr::get() is optimized away because the calling code has checked the error code already.

Matt

On Jun 11, 2020, at 1:58 PM, Thiago Ize <thiago.ize@...> wrote:

std::optional, like most fancy c++ features, is neat on paper, and I'll probably find uses for it once I'm allowed to use C++17, but I get worried it'll still bring too much baggage. For instance, if you use the optional's value(), it'll cause the compiler to generate exception handling code (looking at the assembly I see a std::bad_optional_access can be thrown). If you use value_or() you can avoid the exceptions, which is nice, but you then need to supply the value to use when there's an error which can be either neat or annoying depending on the situation. Even when there's no error, both versions will never be as fast as code that does no error checking (not sure if that matters for imath).

For those curious in trying it out, here's my quick hack at implementing Matt's suggestion: https://gcc.godbolt.org/z/ZYFaap 

Also, the vfx reference platform for 2020 looks to be c++14 (no mention of what will be in 2021), so that might be another impediment even if this is the cleanest approach.

Thiago

On Thu, Jun 11, 2020 at 1:43 PM Matt Pharr <matt.pharr@...> wrote:
Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code, 
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz








Re: Imath: Options for Exceptions

Owen T.
 

Concerning the inventory of exception containing functions in Imath:

Looking at this commit, it can be seen that all the exceptions were identified and changed as to not depend on Iex. This is around 50 calls to Iex exceptions contained in 24 functions with 5 of these already handled using OPTION 1.

Only 7 functions across two files are not in header files already. These would at the very least need to be moved into headers for OPTION 5. 

On 6/11/20 3:29 PM, Larry Gritz wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code,
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz





Re: Imath: Options for Exceptions

Thiago Ize
 

std::optional, like most fancy c++ features, is neat on paper, and I'll probably find uses for it once I'm allowed to use C++17, but I get worried it'll still bring too much baggage. For instance, if you use the optional's value(), it'll cause the compiler to generate exception handling code (looking at the assembly I see a std::bad_optional_access can be thrown). If you use value_or() you can avoid the exceptions, which is nice, but you then need to supply the value to use when there's an error which can be either neat or annoying depending on the situation. Even when there's no error, both versions will never be as fast as code that does no error checking (not sure if that matters for imath).

For those curious in trying it out, here's my quick hack at implementing Matt's suggestion: https://gcc.godbolt.org/z/ZYFaap

Also, the vfx reference platform for 2020 looks to be c++14 (no mention of what will be in 2021), so that might be another impediment even if this is the cleanest approach.

Thiago


On Thu, Jun 11, 2020 at 1:43 PM Matt Pharr <matt.pharr@...> wrote:
Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code,
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz





Re: Imath: Options for Exceptions

Matt Pharr
 

Drive-by: I've seen a nice idiom for this sort of thing in an exception-free codebase that also still gives you error codes (which options 1, 2, and 5 lose). It's effectively

template <typename T, typename ErrorCode>
class ResultOr {
  ErrorCode error;
  std::optional<T> value;
};

with a bunch of methods around it. Methods return a ResultOr object, so can return either a result or an error code, just via "return" statements, thanks to various ResultOr constructors. In the caller, it's then a runtime error to try to access "value" if it wasn't set (so this enforces checking the error code and dealing with it.)

Matt


On Thu, Jun 11, 2020 at 12:29 PM Larry Gritz <lg@...> wrote:
Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code,
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz





Re: Imath: Options for Exceptions

Larry Gritz
 

Oh, these code examples are extremely helpful.

I think Option 1 is inadequate, since it would preclude having the exception-free versions declared properly as 'noexcept'. I think that's an important aspect of this modernization (as well as adding 'noexcept' to the many functions that never had exceptions in the first place).

Aesthetically, I prefer option 2, though it has two acknowledged limitations: (a) On a case-by-case basis, we would need to agree on what would be returned in the error cases (are error-indicating values possible? what should they be?). (b) What to do if/when there are cases where more than one kind of error could occur, and if it's important for calling code to distinguish among them.

Option 3 handles those issues, but despite the precedent from std::filesystem, I think it's kind of ugly how it requires calling code to be littered with declarations of err_code variables, even if you have no intention of checking them (for example, if you know that the surrounding code makes the error condition impossible).

I can think of two other possible approaches (I'm merely listing them for consideration, not necessarily preferring them at this time):

4. Further template on whether we want exceptions (do I remember Kimball Thurston advocating this?).

5. To the extent that we end up with a header-only library, we could allow a preprocessor symbol (set by user code before #include of the Imath headers) to make a strong guarantee of exceptions or not:

#ifndef IMATH_EXCEPTIONS
#  define IMATH_EXCEPTIONS /* bikeshed color goes here */
#endif

#if IMATH_EXCEPTIONS
template<class T>
T Frustum<T>::aspect() const
{
    if (error case)
        throw ...
    return rightMinusLeft / topMinusBottom;
}
#else
template<class T>
T Frustum<T>::aspect() const noexcept
{
    if (error case)
        return T(0);
    return rightMinusLeft / topMinusBottom;
}
#endif


Just out of curiosity, have you done enough of an inventory to know how many functions total we are dealing with that throw exceptions now?


On Jun 11, 2020, at 11:53 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code,
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


--
Larry Gritz





Imath: Options for Exceptions

Owen T.
 

I received a request to introduce an exception free alternative to any Imath function which throws an exception currently. There are a few ways of doing this. If any of them seem superior let me know. Now I am inclined towards option 1 as it has already been used by other parts of Imath.

OPTION 1: Bool parameter (currently used by Matrix inversion functions in Imath, false by default)
template<class T>
T Frustum<T>::aspect(bool singExc) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom) &&
        singExc)
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

OPTION 2: Two differently named functions
template<class T>
T Frustum<T>::aspectExc() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        throw std::domain_error ("Bad viewing frustum: "
                               "aspect ratio cannot be computed.");
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

OPTION 3: Implementation of new 'exc_code'
template<class T>
T Frustum<T>::aspect(exc_code& ec) const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    if (abs(topMinusBottom) < 1 &&
        abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
    {
        ec = ("Bad viewing frustum: "
                  "aspect ratio cannot be computed.");
    //this can be changed to contain other information depending on exc_code,
    }

    return rightMinusLeft / topMinusBottom;
}

template<class T>
T Frustum<T>::aspect() const
{
    T rightMinusLeft = _right-_left;
    T topMinusBottom = _top-_bottom;

    return rightMinusLeft / topMinusBottom;
}

Option 3 is similar to the exception handling of std::filesystem::rename since C++17


Re: Imath: exceptions w/o Iex

Nick Porcino
 

Zero overhead C++ exceptions remain a future fantasy. I'll second what Larry said, and posit that a non-throwing variant should be a baseline requirement, to the degree that the throwing variants can be optionally elided completely. If that means the noexcept code has to go in an isolated namespace, I'm fine with that. A special namespace might be a principled way to move forward.


On Fri, Jun 5, 2020 at 2:26 PM Larry Gritz <lg@...> wrote:
std::domain_error seems more on point

I would certainly like to see, as early in the process as practical, a non-throwing variant of every function that currently uses exceptions.



On Jun 5, 2020, at 1:57 PM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

Seeing as we had decided to remove Iex from Imath I wanted to ask what kind of exceptions should be thrown in lieu of those included in Iex.

For instance, Vec2<T>::normalizeExc() will throw NullVecExc as you can't normalize a vector of length 0.

Should it instead now be std::range_error or something else entirely?


--
Larry Gritz






--
--------------------------------
Nick Porcino @meshula
Virtual and augmented production, interactive applications, and robotics, since 1982


Re: Logo doodle

Nick Porcino
 

I think with a little tightening and brightening, this could look very nice on a T-Shirt or on a piece of hardware.


On Fri, Jun 5, 2020 at 6:51 AM Eskil Steenberg <eskil@...> wrote:
While on the call yesterday I made a doodle. Typography isn't my
strongest suit, but I liked the idea of using the X to illustrate the
notion of linear going beyond the ceiling and floor. I also has some
similarities to the old logo. Maybe its something the designer can use
for inspiration, incorporate in to another design, or completely ignore
:-)

E





--
--------------------------------
Nick Porcino @meshula
Virtual and augmented production, interactive applications, and robotics, since 1982


Re: Imath: exceptions w/o Iex

Larry Gritz
 

std::domain_error seems more on point

I would certainly like to see, as early in the process as practical, a non-throwing variant of every function that currently uses exceptions.



On Jun 5, 2020, at 1:57 PM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

Seeing as we had decided to remove Iex from Imath I wanted to ask what kind of exceptions should be thrown in lieu of those included in Iex.

For instance, Vec2<T>::normalizeExc() will throw NullVecExc as you can't normalize a vector of length 0.

Should it instead now be std::range_error or something else entirely?


--
Larry Gritz





Imath: exceptions w/o Iex

Owen T.
 

Seeing as we had decided to remove Iex from Imath I wanted to ask what kind of exceptions should be thrown in lieu of those included in Iex.

For instance, Vec2<T>::normalizeExc() will throw NullVecExc as you can't normalize a vector of length 0.

Should it instead now be std::range_error or something else entirely?


Logo doodle

Eskil Steenberg
 

While on the call yesterday I made a doodle. Typography isn't my strongest suit, but I liked the idea of using the X to illustrate the notion of linear going beyond the ceiling and floor. I also has some similarities to the old logo. Maybe its something the designer can use for inspiration, incorporate in to another design, or completely ignore :-)

E


Re: Meeting today: Two Questions [Imath]

Larry Gritz
 

We can talk about this on the call, but... must we really bring Iex into Imath?

Does Imath really need exceptions outside standard C++ ones? (Keeping in mind that we can use 'using' to alias the old names to preserve source compatibility.)

Grep says only the following are thrown by Imath (eliminating duplicates):

ImathFrustum.h:        throw IEX_NAMESPACE::ArgExc ("fovx and fovy cannot both be non-zero.");
ImathFrustum.h:        throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: "
ImathMatrix.h:                throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix.");
ImathVec.h: throw NullVecExc ("Cannot normalize null vector.");
ImathVec.h:            throw InfPointExc ("Cannot normalize point at infinity.");
ImathGL.h: throw IEX_NAMESPACE::OverflowExc ("GL matrix overflow");
ImathMatrixAlgo.h: throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ("Cannot remove zero scaling "


These all look like they could be std::out_of_range, std::domain_error, std::overflow_error.


On Thu, Jun 4, 2020 at 11:44 AM Cary Phillips <cary@...> wrote:

Also, we're assuming we lose the term "IlmBase" entirely, and the current subfolders of IlmBase move to the top level of the new repo.  So, the "Imath" repo has subfolders called Imath, ImathTest, Half, HalfTest, Iex, IexMath, IexTest:

...

And IlmThread stays with openexr.

Just confirming, is this what others are expecting?



On Thu, Jun 4, 2020 at 9:09 AM Larry Gritz <lg@...> wrote:
My answers would be:

1. Let's please DON'T support autoconf any more

2. Yes, submodule!


On Jun 4, 2020, at 8:34 AM, Owen T. via lists.aswf.io <ownthmpsn=protonmail.ch@...> wrote:

In today's meeting I want to get a sense of the group's impressions/concerns on two things:

1: Supporting Autoconf building in the new Imath repo (and consequentially OpenEXR as a whole)

    - i.e. is it still necessary or is cmake alone sufficient?

2: Using git submodules to manage Imath installation for OpenEXR

    - This permits: automatically cloning the source of Imath (if it's not detected) and otherwise building almost identically to how OpenEXR does already

    - Information about this can be found here

If there are any concerns I would like to hear them. I heir on the side of not supporting Autoconf, and using the submodules.

Owen Thompson

_

--
Larry Gritz






--
Cary Phillips | R&D Supervisor | ILM | San Francisco



--
Larry Gritz
lg@...