I'm glad you're working on TODO #116.
It's a real pain in the ass when NCO gets a divide by
zero because of this.
Let me expand on the TODO description a bit before
you write a patch:
Most netCDF data is stored as floats or doubles.
#116 never affect these variables, and converting floats
to double precision before arithmetic is a bad idea.
It always has speed/memory penalties and gives
no advantage in precision in 99.99% of all cases.
So people who want double precision arithmetic should
store their data as double. Period.
So the fix to #116 should only affect arithmetic operations
on long,short, char, and byte types. Basically we don't
do anything to char's and byte's anyway so they are a
non-issue. But there is value in being able to, say, average
multiple bitmaps stored as unsigned chars (I've had complaints
from users who actually need this capability!) so this fix will
help to make possible some useful operations.
Anyway, I'm thinking that the best fix is to convert
long,short,byte, and char types to double precision
before arithmetic and then back afterwards, and leave
the floats alone.
I don't know how hard this will be to implement.
It may require expanding the variable
structure so that variables "remember" their original
types, but maybe the operators themselves should
handle that. That's up to you.
Charlie
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Charlie,
When converting numbers back from double precision to shorts
or longs I get a SIGEGV error in var_conform_type. I am
reluctant to make changes to var_conform_type as i may
break soemthing else. What do you recommend ?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I do not understand why this is happening.
Can you send me an example of a short which converts to a
double but gives an error when converting back to a short?
It may be an integer with a non-exact representation as a double,
but I thought doubles used enough bits in the mantissa to represent
all shorts and longs exactly. Am I wrong?
This code snippet appears to work:
val_dbl=(double)sht_foo; /* Cast short to double */
val_sht=(short)val_dbl; /* Cast double back to short */
(void)fprintf(stdout,"%s: sht_foo = %d, val_dbl=%f, val_sht=%d\n",prg_nm,sht_foo,val_dbl,val_sht);
So I'm sure we can fix the problem you found
if we can isolate the values that trigger it.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Note that performing arithmetic operations on shorts that have
been converted to doubles may lead to "errors" when the results
are converted back to short.
e.g., if they use -y avgsqr on a value of 1000 then the double
answer is 1000000 which, when converted back to short is
16960. At least on Linux the conversions always work for me
in that they do not produce errors. Conversions seems to be
handled correctly modulo the largest representable value
in the destination type.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Charlie,
var_conform_type does not seem to perform a complete confersion of type . After the values are read in from disk .
I perform a conversion and the type written out is still the
original type but with messed up variables.
E.G With shorts , even after conversion to doubles and the
fact that var_prc[idx]->type = NC_DOUBLE , shorts get written to disk
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If shorts are read in from disk then shorts should be written out to disk.
So that's no surprise. In all operators the output file is set up before
any arithmetic is performed. So the output file is expecting a short
to still be a short. Just so we are on the same wavelength, I think
only the arithmetic should be performed in double precision (and
only for shorts/long/byte/char) and the result should be converted
back to the original type of data. The C language does something
similar with floats but we don't want to do that.
var_conform_type() works with ncwa's current features. Maybe it needs
to be tweaked to accomplish what you are trying, I won't know unless
you post a patch. Be careful to make sure you are converting both the
variable and its missing_value, if any, to doubles.
Could it be that that all you need to do is to convert back to shorts
after the arithmetic and things will begin to work fine?
In other words set a flag that a variable has been converted
then check for the flag after the arithmetic to convert back?
Keep me posted. I keep tagging and untagging version 1.2 but
it's basically done except for some final documentation issues.
It's on the homepage already.
Thanks,
Charlie
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Charlie,
Have finally submitted a patch for conversions to double
prescision. Sorry about making a mountain out of a molehill.
Its just that so much is going on in ncwa that its hard to
get a handle on things. In the end it was much easier than
I thought. I don't bother to convert back var_prc becouse the values needed are all in var_prc_out and I get a core dump when I try to convert back. I think the patch needs
testing with some large multivariable files
regards Henry
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
OK, this patch looks good. Smaller than I was expecting, too.
I CVS'd my mods to your patch. Take a look at the new
version, tested ncwa test cases 31, 32 in nco_tst.sh.
Can you add similar hooks to ncra.c and ncflint.c?
Once we get those operators modified we should release 1.2.1.
Also there's a new Type Conversion portion of the manual.
Comments/edits welcome.
Charlie
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I created the necessary patch for ncra/ncea, but not for ncflint.
Since ncra and ncea read in variables multiple times (once per
record/file), I had to change the logic of the type conversion
routines. The new logic appears to work and should be more
suitable for adding scale_factor/add_offset capability for packing
and unpacking. The file pck.c contains some preliminary routines
to handle packing issues. The type conversion stuff is now
publically released in nco-1.2.1
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Henry (and lurkers),
I'm glad you're working on TODO #116.
It's a real pain in the ass when NCO gets a divide by
zero because of this.
Let me expand on the TODO description a bit before
you write a patch:
Most netCDF data is stored as floats or doubles.
#116 never affect these variables, and converting floats
to double precision before arithmetic is a bad idea.
It always has speed/memory penalties and gives
no advantage in precision in 99.99% of all cases.
So people who want double precision arithmetic should
store their data as double. Period.
So the fix to #116 should only affect arithmetic operations
on long,short, char, and byte types. Basically we don't
do anything to char's and byte's anyway so they are a
non-issue. But there is value in being able to, say, average
multiple bitmaps stored as unsigned chars (I've had complaints
from users who actually need this capability!) so this fix will
help to make possible some useful operations.
Anyway, I'm thinking that the best fix is to convert
long,short,byte, and char types to double precision
before arithmetic and then back afterwards, and leave
the floats alone.
I don't know how hard this will be to implement.
It may require expanding the variable
structure so that variables "remember" their original
types, but maybe the operators themselves should
handle that. That's up to you.
Charlie
Hi Charlie,
When converting numbers back from double precision to shorts
or longs I get a SIGEGV error in var_conform_type. I am
reluctant to make changes to var_conform_type as i may
break soemthing else. What do you recommend ?
I do not understand why this is happening.
Can you send me an example of a short which converts to a
double but gives an error when converting back to a short?
It may be an integer with a non-exact representation as a double,
but I thought doubles used enough bits in the mantissa to represent
all shorts and longs exactly. Am I wrong?
This code snippet appears to work:
val_dbl=(double)sht_foo; /* Cast short to double */
val_sht=(short)val_dbl; /* Cast double back to short */
(void)fprintf(stdout,"%s: sht_foo = %d, val_dbl=%f, val_sht=%d\n",prg_nm,sht_foo,val_dbl,val_sht);
So I'm sure we can fix the problem you found
if we can isolate the values that trigger it.
Note that performing arithmetic operations on shorts that have
been converted to doubles may lead to "errors" when the results
are converted back to short.
e.g., if they use -y avgsqr on a value of 1000 then the double
answer is 1000000 which, when converted back to short is
16960. At least on Linux the conversions always work for me
in that they do not produce errors. Conversions seems to be
handled correctly modulo the largest representable value
in the destination type.
Charlie,
var_conform_type does not seem to perform a complete confersion of type . After the values are read in from disk .
I perform a conversion and the type written out is still the
original type but with messed up variables.
E.G With shorts , even after conversion to doubles and the
fact that var_prc[idx]->type = NC_DOUBLE , shorts get written to disk
Henry,
If shorts are read in from disk then shorts should be written out to disk.
So that's no surprise. In all operators the output file is set up before
any arithmetic is performed. So the output file is expecting a short
to still be a short. Just so we are on the same wavelength, I think
only the arithmetic should be performed in double precision (and
only for shorts/long/byte/char) and the result should be converted
back to the original type of data. The C language does something
similar with floats but we don't want to do that.
var_conform_type() works with ncwa's current features. Maybe it needs
to be tweaked to accomplish what you are trying, I won't know unless
you post a patch. Be careful to make sure you are converting both the
variable and its missing_value, if any, to doubles.
Could it be that that all you need to do is to convert back to shorts
after the arithmetic and things will begin to work fine?
In other words set a flag that a variable has been converted
then check for the flag after the arithmetic to convert back?
Keep me posted. I keep tagging and untagging version 1.2 but
it's basically done except for some final documentation issues.
It's on the homepage already.
Thanks,
Charlie
Hi Charlie,
Have finally submitted a patch for conversions to double
prescision. Sorry about making a mountain out of a molehill.
Its just that so much is going on in ncwa that its hard to
get a handle on things. In the end it was much easier than
I thought. I don't bother to convert back var_prc becouse the values needed are all in var_prc_out and I get a core dump when I try to convert back. I think the patch needs
testing with some large multivariable files
regards Henry
Henry,
OK, this patch looks good. Smaller than I was expecting, too.
I CVS'd my mods to your patch. Take a look at the new
version, tested ncwa test cases 31, 32 in nco_tst.sh.
Can you add similar hooks to ncra.c and ncflint.c?
Once we get those operators modified we should release 1.2.1.
Also there's a new Type Conversion portion of the manual.
Comments/edits welcome.
Charlie
I created the necessary patch for ncra/ncea, but not for ncflint.
Since ncra and ncea read in variables multiple times (once per
record/file), I had to change the logic of the type conversion
routines. The new logic appears to work and should be more
suitable for adding scale_factor/add_offset capability for packing
and unpacking. The file pck.c contains some preliminary routines
to handle packing issues. The type conversion stuff is now
publically released in nco-1.2.1