Bug in the routine converting RGB to TSL and back - rgb

I am trying the TSL color space (Tint Saturation Luminance). Reading this wiki page
TSL color space
I have tried to code two simple rgb2tsl and tsl2rgb routines:
/// input: r,g,b in [0..1]
/// output: t,s,l in [0..1]
void RGB2TSL( float r, float g, float b, float &t, float &s, float &l )
{
float rn, gn;
if ( r+g+b == 0.0f )
{
t = s = l = 0.0f;
return ;
}
rn = r/(r+g+b);
gn = g/(r+g+b);
float r1, g1;
r1 = rn-1.0f/3.0f;
g1 = gn-1.0f/3.0f;
l = 0.299*r+0.587*g+0.114*b;
if ( g1 > 0 )
t = (1.0f/(2.0f*PI))*atan2f(r1, g1) + 1.0f/4.0f;
else if ( g1 < 0 )
t = (1.0f/(2.0f*PI))*atan2f(r1, g1) + 3.0f/4.0f;
else
t = 0;
s = sqrtf(9.0f/5.0f*(r1*r1+g1*g1));
}
/// input: t,s,l in [0..1]
/// output: r,g,b in [0..1]
void TSL2RGB( float t, float s, float l, float &r, float &g, float &b )
{
float r1, g1, k, x;
x = -sinf(2*PI*t);
if ( x != 0 )
x = cosf(2*PI*t)/x;
if ( t > 0.5f )
g1 = -s*sqrtf(5.0f/(9.0*(x*x+1.0f)));
else if ( t < 0.5f )
g1 = s*sqrtf(5.0f/(9.0*(x*x+1.0f)));
else
g1 = 0;
if ( t == 0 )
r1 = (sqrtf(5.0f)/3.0f)*s;
else
r1 = x*g1+1.0f/3.0f;
k = 1.0f/(0.185*r1+0.473*g1+0.114);
r = k*r1;
g = k*g1;
b = k*(1-r1-g1);
}
Please don't consider the code quality, just focus on the fact that there is an error I am unable to find: when I convert a rgb triple to tsl triple and, without changing anything, I convert it back to r, g, b, I don't get the original image, but really different and wrong in any possible way!

RGB2TSL looks good to me, however there are clipping issues I believe. I think some values need to be clamped, but I'm not sure myself exactly which ones.

Related

C function call Numerical Recipes Chapter 10.3

I have this function. I'm kinda green in C and I don't know how to call this function to get a result:
float dbrent(float ax, float bx, float cx, float (*f)(float),float (*df)(float), float tol, float* xmin)
{
int iter, ok1, ok2;
float a, b, d, d1, d2, du, dv, dw, dx, e = 0.0;
float fu, fv, fw, fx, olde, tol1, tol2, u, u1, u2, v, w, x, xm;
a = (ax < cx ? ax : cx);
b = (ax > cx ? ax : cx);
x = w = v = bx;
fw = fv = fx = (*f)(x);
dw = dv = dx = (*df)(x);
for (iter = 1; iter <= ITMAX; iter++)
{
xm = 0.5 * (a + b);
tol1 = tol * fabs(x) + ZEPS;
tol2 = 2.0 * tol1;
if (fabs(x - xm) <= (tol2 - 0.5 * (b - a))) {
*xmin = x;
return fx;
}
if (fabs(e) > tol1) {
d1 = 2.0 * (b - a);
d2 = d1;
if (dw != dx) d1 = (w - x) * dx / (dx - dw);
if (dv != dx) d2 = (v - x) * dx / (dx - dv);
u1 = x + d1;
u2 = x + d2;
ok1 = (a - u1) * (u1 - b) > 0.0 && dx * d1 <= 0.0;
ok2 = (a - u2) * (u2 - b) > 0.0 && dx * d2 <= 0.0;
olde = e;
e = d;
if (ok1 || ok2) {
if (ok1 && ok2)
d = (fabs(d1) < fabs(d2) ? d1 : d2);
else if (ok1)
d = d1;
else
d = d2;
if (fabs(d) <= fabs(0.5 * olde)) {
u = x + d;
if (u - a < tol2 || b - u < tol2)
d = SIGN(tol1, xm - x);
}
else {
d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
}
}
else {
d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
}
}
else {
d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
}
if (fabs(d) >= tol1) {
u = x + d;
fu = (*f)(u);
}
else {
u = x + SIGN(tol1, d);
fu = (*f)(u);
if (fu > fx) {
*xmin = x;
return fx;
}
}
du = (*df)(u);
if (fu <= fx) {
if (u >= x) a = x; else b = x;
MOV3(v, fv, dv, w, fw, dw)
MOV3(w, fw, dw, x, fx, dx)
MOV3(x, fx, dx, u, fu, du)
}
else {
if (u < x) a = u; else b = u;
if (fu <= fw || w == x) {
MOV3(v, fv, dv, w, fw, dw)
MOV3(w, fw, dw, u, fu, du)
}
else if (fu < fv || v == x || v == w) {
MOV3(v, fv, dv, u, fu, du)
}
}
}
cout<<"Too many iterations in routine dbrent";
return 0.0;
}
This code is from Numerical Recipes Chapter 10.3. I need to call this function and get the result but I don't know how to call it, especially when there is a syntax like float (*)(float).
Thanks in advance.
Well, let's suppose you have the following functions:
float df_(float yourFloat) {
...
return yourFloat;
}
and
float f_(float yourFloat) {
...
return yourFloat;
}
Then you could call your function as follows:
float t = dbrent(ax, bx, cx, &f_, &df_, tol, &xmin);
Where &xmin hands over the address of some float variable xmin.
So, in essence, you supply the address of your functions f_ and df_ and your float variable xmin.
We can call dbrent in several ways, the below shown is one of the ways.
Your function prototype
float dbrent ( float ax, float bx, float cx,
float (*f)(float),
float (*df)(float),
float tol, float* xmin
)
what you need is a func_f (you can use any name for function) that takes a float value as an argument and returns a float value as shown below.
float func_f(float num)
{
/* code */
}
you need one more function with same type as mentioned above
float func_df(float num)
{
/* code */
}
Following is the setup you need to make before calling dbrent
some_funtion()
{
// setup to call dbrent
// guess you know you need some values in it.
float ax, bx, cx, tol, xmin;
float (*f)(float);
float (*df)(float);
f = func_f;
df = func_df;
//one way of calling dbrent
dbrent(ax, bx, cx, f, df,tol, xmin);
//you can even directly call using the function names instead of using pointers
dbrent(ax, bx, cx, func_f, func_df, tol, xmin);
}
NOTE: variables have not been initialized for simplicity, make sure you pass valid variables when calling the function.

How to estimate multiplicity of the polynomial root?

I want to estimate multiplicity of polynomial roots.
I have found some info about it, choosed the test example and made c program
Here should be 4 roots. One simple root and one with multiplicity 3.
#include <complex.h>
#include <math.h>
#include <stdio.h>
complex long double z0 = +1.5; // exact period = 1 stability = 3.000000000000000000 multiplicity = ?
complex long double z1 = -0.5; // exact period = 2 stability = 0.999999999999900080 multiplicity = ?
complex long double c = -0.75; // parameter of the f function
/*
https://en.wikibooks.org/wiki/Fractals/Mathematics/Newton_method
*/
int GiveMultiplicity(const complex long double c, const complex long double z0 , const int pMax){
complex long double z = z0;
complex long double d = 1.0; /* d = first derivative with respect to z */
complex long double e = 0.0; // second derivative with respect to z
complex long double m;
int multiplicity;
int p;
for (p=0; p < pMax; p++){
d = 2*z*d; // f' = first derivative with respect to z */
e = 2*(d*d +z*e); // f'' = second derivative with respect to z
z = z*z +c ; // f = complex quadratic polynomial
}
m = (d*d)/(d*d -z*e);
multiplicity = (int) round(cabs(m));
return multiplicity;
}
int main(){
int m;
m = GiveMultiplicity(c, z0, 1);
printf("m = %d \n", m);
m = GiveMultiplicity(c, z1, 1);
printf("m = %d \n", m);
m = GiveMultiplicity(c, z1, 2);
printf("m = %d \n", m);
return 0;
}
The result is :
m=1
m=1
m=1
Is it good ? Maybe I should simply add the results ?
Good results using symbolic computations are roots: [ 3/2, -1/2] and its multiplicities : [1,3]
Here is a graph of the function f(z)= (z^2-0.75)^2-z-0.75 = z^4-1.5*z^2-z-3/16
Is it possibly to compute the similar values numerically ?
You do this with contour integration, see here. Software is available.
Summary of changes:
evaluate e before evaluating d inside the loop;
when subtracting z0 from z after the loop, you also need to subtract 1 from d to match;
perturb input a small amount from true root location to avoid 0/0 = NaN result: h must be small enough, but not too small...
Complete program:
#include <complex.h>
#include <math.h>
#include <stdio.h>
complex long double h = 1.0e-6; // perturb a little; not too big, not too small
complex long double z0 = +1.5; // exact period = 1 stability = 3.000000000000000000 multiplicity = ?
complex long double z1 = -0.5; // exact period = 2 stability = 0.999999999999900080 multiplicity = ?
complex long double c = -0.75; // parameter of the f function
/*
https://en.wikibooks.org/wiki/Fractals/Mathematics/Newton_method
*/
int GiveMultiplicity(const complex long double c, const complex long double z0, const int pMax){
complex long double z = z0;
complex long double d = 1.0; /* d = first derivative with respect to z */
complex long double e = 0.0; // second derivative with respect to z
complex long double m;
int multiplicity;
int p;
for (p=0; p < pMax; p++){
e = 2*(d*d +z*e); // f'' = second derivative with respect to z
d = 2*z*d; // f' = first derivative with respect to z */
z = z*z +c ; // f = complex quadratic polynomial
}
d = d - 1;
z = z - z0;
m = (d*d)/(d*d -z*e);
multiplicity = (int) round(cabs(m));
return multiplicity;
}
int main(){
int m;
m = GiveMultiplicity(c, z0 + h, 1);
printf("m = %d\n", m);
m = GiveMultiplicity(c, z1 + h, 1);
printf("m = %d\n", m);
m = GiveMultiplicity(c, z1 + h, 2);
printf("m = %d\n", m);
return 0;
}
Output:
m = 1
m = 1
m = 3
I have found one error im my initial program. Function for finding periodic points should be
f^n(z) - z
so
for (p=0; p < pMax; p++){
d = 2*z*d; // f' = first derivative with respect to z */
e = 2*(d*d +z*e); // f'' = second derivative with respect to z
z = z*z +c ; // f = complex quadratic polynomial
}
z = z - z0; // new line
I have choosed the method based on the geometrical notation of the root
It is described in The Fundamental Theorem of Algebra: A Visual Approach by Daniel J. Velleman
I count how many times color chages along a circle around root.
I use carg function which returns the phase angle of z in the interval [−π; π]. So count the sign change of the argument and divide it by 2. This estimates the multiplicity of the root.
It is probly the same method as above, but easier to understand and implement for me.
Here is the image of dynamical plane
before transformation:
and after f(z):
and the code:
// gcc p.c -Wall -lm
// ./a.out
#include <complex.h>
#include <math.h>
#include <stdio.h>
// parameter c of the function fc(z) = z^2+c is c = -0.7500000000000000 ; 0.0000000000000000
const long double pi = 3.1415926535897932384626433832795029L;
long double EPS2 = 1e-18L*1e-18L; //
complex double c = -0.75;
complex double z = 1.5; //-0.5;
//https://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
int sign(long double x){
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
int DifferentSign(long double x, long double y){
if (sign(x)!=sign(y)) return 1;
return 0;
}
long double complex Give_z0(long double InternalAngleInTurns, long double radius )
{
//0 <= InternalAngleInTurns <=1
long double a = InternalAngleInTurns *2.0*pi; // from turns to radians
long double Cx, Cy; /* C = Cx+Cy*i */
Cx = radius*cosl(a);
Cy = radius*sinl(a);
return Cx + Cy*I;
}
int GiveMultiplicity(complex long double zr, int pMax){
int s; // number of starting point z0
int sMax = 5*pMax; // it should be greater then 2*pMax
long double t= 0.0; // angle of circle around zr, measured in turns
long double dt = 1.0 / sMax; // t step
long double radius = 0.001; // radius should be smaller then minimal distance between roots
int p;
long double arg_old = 0.0;
long double arg_new = 0.0;
int change = 0;
complex long double z;
complex long double z0;
//complex long double zp;
//
for (s=0; s<sMax; ++s){
z0 = zr + Give_z0(t, radius); // z = point on the circle around root zr
// compute zp = f^p(z)
z = z0;
for (p=0; p < pMax; ++p){z = z*z + c ;} /* complex quadratic polynomial */
// turn (zp-z0)
z = z - z0; // equation for periodic_points of f for period p
arg_new = carg(z);
if (DifferentSign(arg_new, arg_old)) {change+=1;}
arg_old = arg_new;
//printf("z0 = %.16f %.16f zp = %.16f %.16f\n", creal(z0), cimag(z0), creal(zp), cimag(zp));
t += dt; // next angle using globl variable dt
}
return change/2;
}
int main(){
printf("multiplicity = %d\n", GiveMultiplicity(z,2));
return 0;
}
And here is the image of argument of z around root ( it uses carg )

Generate a random point in a specific plane in C

I have a 2D plane in three dimensions: x+y+z=1, and I want to generate random points(x,y,z) on the plane. How can I choose these points so that they are distributed uniformly?
The Problem
As mentioned in the comments, the question was under specified. Despite that it's a interesting question. Because no distribution was given I just picked one. Here is the more precise(?)/general(?) question I will answer:
Suppose I have a plane P in R^3 defined by ax + by + cz = d.
Let c be in the point on P closest to the origin.
How can I uniformly choose a point on P within some radius r of c?
The Algorithm
Let n = (a,b,c). n is the vector normal to P.
direction
Generate any non-zero vector on the plane ax + by + cz = d, call it w. You can do this by taking the cross product of n with any non-zero vector not parallel to n.
Rotate w around n by a random angle in [0,2pi). You can do this using http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula.
so , now you got direction by normalizing it
direction = direction / direction.magnitude
origin of the ray
If d is 0, we're done. Otherwise:
Calculate c = distance of plane from Vector3(0 , 0 , 0)
according to http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_plane.
Translate Origin of ray
origin of the ray = vector3.zero + c * ( n )
scale = random.range(min , max)
So the point is
origin_of_the_ray + scale * (direction_)
The Code
Here is my C implementation of the algorithm. I wrote all the vector machinery from scratch so it's a little messy. I have not tested this throughly.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
typedef struct {
double x, y, z;
} vec3;
vec3 vec(double x, double y, double z);
vec3 crossp(vec3 u, vec3 v);
vec3 add(vec3 u, vec3 v);
double dotp(vec3 u, vec3 v);
double norm2(vec3 u);
double norm(vec3 u);
vec3 scale(vec3 u, double s);
vec3 normalize(vec3 u);
void print_vec3(vec3 u);
// generates a random point on the plane ax + by + cz = d
vec3 random_on_plane(double r, double a, double b, double c, double d) {
// The normal vector for the plane
vec3 n = vec(a, b, c);
// create a normal vector on the plane ax + by + cz = 0
// we take any vector not parallel to n
// and find the cross product
vec3 w;
if (n.x == 0)
w = crossp(n, vec(1,0,0));
else
w = crossp(n, vec(0,0,1));
// rotate the vector around n by a random angle
// using Rodrigues' rotation formula
// http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
double theta = ((double)rand() / RAND_MAX) * M_PI;
vec3 k = normalize(n);
w = add(scale(w, cos(theta)),
scale(crossp(k, w), sin(theta)));
// Scale the vector fill our disk.
// If the radius is zero, generate unit vectors
if (r == 0) {
w = scale(w, r/norm(w));
} else {
double rand_r = ((double)rand() / RAND_MAX) * r;
w = scale(w, rand_r/norm(w));
}
// now translate the vector from ax + by + cz = 0
// to the plane ax + by + cz = d
// http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_plane
if (d != 0) {
vec3 t = scale(n, d / norm2(n));
w = add(w, t);
}
return w;
}
int main(void) {
int i;
srand(time(NULL));
for (i = 0; i < 100; i++) {
vec3 r = random_on_plane(10, 1, 1, 1, 1);
printf("random v = ");
print_vec3(r);
printf("sum = %f, norm = %f\n", r.x + r.y + r.z, norm(r));
}
}
vec3 vec(double x, double y, double z) {
vec3 u;
u.x = x;
u.y = y;
u.z = z;
return u;
}
vec3 crossp(vec3 u, vec3 v) {
vec3 w;
w.x = (u.y * v.z) - (u.z * v.y);
w.y = (u.z * v.x) - (u.x * v.z);
w.z = (u.x * v.y) - (u.y * v.x);
return w;
}
double dotp(vec3 u, vec3 v) {
return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
}
double norm2(vec3 u) {
return dotp(u, u);
}
double norm(vec3 u) {
return sqrt(norm2(u));
}
vec3 scale(vec3 u, double s) {
u.x *= s;
u.y *= s;
u.z *= s;
return u;
}
vec3 add(vec3 u, vec3 v) {
u.x += v.x;
u.y += v.y;
u.z += v.z;
return u;
}
vec3 normalize(vec3 u) {
return scale(u, 1/norm(u));
}
void print_vec3(vec3 u) {
printf("%f %f %f\n", u.x, u.y, u.z);
}
Eugene had it almost right: generate two random numbers on the interval [0,1), call them A, B. Then x = min(A,B), y = max(A,B) - x, z = 1 - (x + y). Basically, you pick two points on the line [0,1) and your three coordinates are the three intervals defined by those two points.
I'll first give you a simple algorithm
x = rand()
y = rand()
z = 1 - x - y
Now lets see an implementation of that algorithm
This code will produce any sort of numbers ( +ve or -ve )
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
srand(time(NULL));
int x= ( rand() - rand() ) ;
int y= ( rand() - rand() ) ;
int z=1-x-y;
printf("x=%d y=%d z=%d",x,y,z);
}
just use srand() to seed the random number generator, and use rand() to assign a random number.
If you need to create random numbers with a range, then use rand() % ( maxnumber + 1 ) where maxnumber is the maximum value you want.
If you want all of your numbers to be positive, then try this
int main()
{
srand(time(NULL));
int x, y , z = -1;
while ( z < 0 )
{
x = rand() ;
y = rand() ;
z = 1 - (x + y );
}
printf("x=%d y=%d z=%d",x,y,z);
}
WARNING
the above code might take some time to execute, so don't expect an instant result

Calculating exponents in C without pow()

int main ()
{
int n = 0;
int base = 0;
while(n < 10)
{
int x = 2;
int answer = power(x, n);
float neganswer = negpower(x, n);
printf("%d %d %f\n", base, answer, neganswer);
base++;
n++;
}
return EXIT_SUCCESS;
}
int power(int base, int power)
{
int result, i;
result = 1;
for (i=0; i < power; i++)
{
result *= base;
}
return result;
}
int negpower(int base, int power)
{
float result, i;
result = 1.0;
for (i=0; i < power; i++)
{
result = result / base;
}
return result;
}
So I'm trying to call upon this function that i've made, and I think its calculating it correctly, however it is only outputting 1.0000000 followed directly by 0.0000000. I think I've got problems with carrying the float value, can anyone chime in?
Thanks
This is because you are returning a float from negpower() which has return type of int and assigning it to a float neganswer.
Change
int negpower(int base, int power)
to
float negpower(int base, int power)
Output:
Side note:
Always add required header files.
A prototype should be declared if a function definition appears after the main().
The answer is much simpler. Your negpower function returns an int, when you actually return a float from it. Change the prototype and it should work alright.
This is optimized library if you are interested:
#ifdef DOCUMENTATION
title pow x raised to power y
index x raised to power y
usage
.s
double x, y, f, pow();
.br
f = pow(x, y);
.s
description
.s
Returns value of x raised to power y
.s
diagnostics
.s
There are three error possible error messages from this function.
.s
If the x argument is negative the message 'pow arg negative',
followed by the value of x, is written to stderr. The value
of pow for |x| is returned.
.s
If x = 0.0 and y <= 0.0 or if result overflows the message 'pow
overflow', followed by the value of y, is written to stderr.
The value of HUGE is returned.
.s
If the result underflows and if warnings are enabled (normally not),
the message 'pow underflow', followed by the value of y, is written
to stderr. The value of 0 is returned.
.s
The suggestion of Cody and Waite, that the domain be reduced to
simplify the overflow test, has been adopted, consequently overflow
is reported if the result would exceed HUGE * 2**(-1/16).
2**(-1/16) is approximately 0.9576.
.s
internal
.s
Algorithm from Cody and Waite pp. 84-124. This algorithm required
two auxiliary programs POWGA1 and POWGA2 to calculate, respectively,
the arrays a1[] and a2[] used to represent the powers of 2**(-1/16)
to more than machine precision.
The source code for these programs are in the files POWGA1.AUX and
POWGA2.AUX. The octal table on page 98 of Cody and Waite is in the
file POWOCT.DAT which is required on stdin by POWGA2.
.s
author
.s
Hamish Ross.
.s
date
.s
27-Jan-85
#endif
#include <math.h>
#define MAXEXP 2031 /* (MAX_EXP * 16) - 1 */
#define MINEXP -2047 /* (MIN_EXP * 16) - 1 */
static double a1[] = {
1.0,
0.95760328069857365,
0.91700404320467123,
0.87812608018664974,
0.84089641525371454,
0.80524516597462716,
0.77110541270397041,
0.73841307296974966,
0.70710678118654752,
0.67712777346844637,
0.64841977732550483,
0.62092890603674203,
0.59460355750136054,
0.56939431737834583,
0.54525386633262883,
0.52213689121370692,
0.50000000000000000
};
static double a2[] = {
0.24114209503420288E-17,
0.92291566937243079E-18,
-0.15241915231122319E-17,
-0.35421849765286817E-17,
-0.31286215245415074E-17,
-0.44654376565694490E-17,
0.29306999570789681E-17,
0.11260851040933474E-17
};
static double p1 = 0.833333333333332114e-1;
static double p2 = 0.125000000005037992e-1;
static double p3 = 0.223214212859242590e-2;
static double p4 = 0.434457756721631196e-3;
static double q1 = 0.693147180559945296e0;
static double q2 = 0.240226506959095371e0;
static double q3 = 0.555041086640855953e-1;
static double q4 = 0.961812905951724170e-2;
static double q5 = 0.133335413135857847e-2;
static double q6 = 0.154002904409897646e-3;
static double q7 = 0.149288526805956082e-4;
static double k = 0.442695040888963407;
double pow(x, y)
double x, y;
{
double frexp(), g, ldexp(), r, u1, u2, v, w, w1, w2, y1, y2, z;
int iw1, m, p;
if (y == 0.0)
return(1.0);
if (x <= 0.0) {
if (x == 0.0) {
if (y > 0.0)
return(x);
cmemsg(FP_POWO, &y);
return(HUGE);
}
else {
cmemsg(FP_POWN, &x);
x = -x;
}
}
g = frexp(x, &m);
p = 0;
if (g <= a1[8])
p = 8;
if (g <= a1[p + 4])
p += 4;
if (g <= a1[p + 2])
p += 2;
p++;
z = ((g - a1[p]) - a2[p / 2]) / (g + a1[p]);
z += z;
v = z * z;
r = (((p4 * v + p3) * v + p2) * v + p1) * v * z;
r += k * r;
u2 = (r + z * k) + z;
u1 = 0.0625 * (double)(16 * m - p);
y1 = 0.0625 * (double)((int)(16.0 * y));
y2 = y - y1;
w = u2 * y + u1 * y2;
w1 = 0.0625 * (double)((int)(16.0 * w));
w2 = w - w1;
w = w1 + u1 * y1;
w1 = 0.0625 * (double)((int)(16.0 * w));
w2 += (w - w1);
w = 0.0625 * (double)((int)(16.0 * w2));
iw1 = 16.0 * (w1 + w);
w2 -= w;
while (w2 > 0.0) {
iw1++;
w2 -= 0.0625;
}
if (iw1 > MAXEXP) {
cmemsg(FP_POWO, &y);
return(HUGE);
}
if (iw1 < MINEXP) {
cmemsg(FP_POWU, &y);
return(0.0);
}
m = iw1 / 16;
if (iw1 >= 0)
m++;
p = 16 * m - iw1;
z = ((((((q7*w2 + q6)*w2 + q5)*w2 + q4)*w2 + q3)*w2 + q2)*w2 + q1)*w2;
z = a1[p] + a1[p] * z;
return(ldexp(z, m));
}
You have all sorts of ints in there. When you do that, the decimal gets truncated. You should make your power functions return floats, and use a float base.

Sort Red, Green Blue using C

this is my first time using Stack Overflow, and I must warn you that I only started to learn C earlier this week. I am trying to write a simple program that will find which color has the greatest value out of the RGB spectrum. It has a manual input for each color, but when It is finished, I am getting 2 odd numbers ranging in the millions. Could somebody help a noob? Here is the code that I've written so far:
#include <stdio.h>
int main()
{
int mm, m;
int hh, h;
int r, g, b, c;
printf("Enter Value For Red (0-255)\n");
scanf("%d", &r);
printf("Enter Value For Green (0-255)\n");
scanf("%d", &g);
printf("Enter Value For Blue (0-255)\n");
scanf("%d", &b);
if ( r > g );
if ( r > b );
mm = r;
if ( g > b );
m = b;
if ( b > g );
m = g;
if ( r < b );
mm = b;
m = g;
if ( g > r );
if ( g > b );
mm = g;
if ( r > b );
m = b;
if ( b > r );
m = r;
if ( g < b );
mm = b;
m = r;
printf("%d\n", &mm);
printf("%d\n", &m);
}
printf("%d\n", &mm);
printf("%d\n", &m);
Should be:
printf("%d\n", mm);
printf("%d\n", m);
The & gets the address of the variable. When you're setting a variable via scanf() you need to give the address so that it can be set. When you're printting the value of a variable via printf() you need to just provide the name, not the address.
What you're seeing right now is the address of where your variables are stored on the stack as a decimal number.
Side note, your code doesn't work the way you think it does:
if ( r > g );
if ( r > b );
mm = r;
if ( g > b );
m = b;
if ( b > g );
m = g;
if ( r < b );
mm = b;
m = g;
It takes more then indentation to get this working, right now it's doing the following:
mm = r;
m = b;
m = g;
mm = b;
...
everytime you run it, because the if's are being chucked. You can't have ; after an if statement or it doesn't do what's below it. Also use curly brackets { } to make a scope to do more then one thing:
if ( r > g )
{
if ( r > b )
{
mm = r;
if ( g > b )
m = b;
if ( b > g )
m = g;
}
if ( r < b )
{
mm = b;
m = g;
...
Is what you wanted.
There is a reason scanf() accepts pointers to its arguments: it has to modify them.
However, printf() does not modify its arguments (generally... - there are exceptions), so you don't have to pass it pointers. Change
printf("%d\n", &mm);
printf("%d\n", &m);
to
printf("%d\n", mm);
printf("%d\n", m);
You should make use of { and } after your ifs. Your form of if ( r > g ); does hardly work. Especially the semi-colons are wrong here.

Resources