I have a class with dimensions written in consts for all UI elements used in my app. Suddenly I noticed that things looks different on 6 and 4 iphone, so I need to adjust numbers slightly. But when i want to use conditionals to detect device and assign correct values to constants, it gives me "token is not a valid binary operator in a preprocessor subexpression".
Code below:
#import <UIKit/UIKit.h>
#import "UIStyles.h"
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#implementation UIStyles
#if (IS_IPHONE_4_OR_LESS)
const int BOTTOM_BTN_HEIGHT = 40;
const int PRICE_AND_LOCATION_BAR_HEIGHT = 40;
#else
const int BOTTOM_BTN_HEIGHT = 50;
const int PRICE_AND_LOCATION_BAR_HEIGHT = 50;
#endif
#end
Try the below way...
#if defined(IS_IPHONE_6)
const int BOTTOM_BTN_HEIGHT = 40;
const int PRICE_AND_LOCATION_BAR_HEIGHT = 40;
#else
const int BOTTOM_BTN_HEIGHT = 50;
const int PRICE_AND_LOCATION_BAR_HEIGHT = 50;
#endif
Out side you can try like this:
NSLog(#"Botton Height : %d",IS_IPHONE_6);
I suppose that you shoud create a function for separate this devices. Seems that your compiller couldn't call [[UIScreen mainScreen] bounds].size.width on preprocessing). This is not calling for replace as I think...
Related
I'm switching from an old Intel 86-64 MacBook Air to a new M1 MacBook Pro.
I'm having some problems using the library Cuba, in particular the (ll)Vegas integrator: while on the former pc everything was working properly, while in the latter (with the same compiler g++-12 and the same extra libraries required for my code) I get a generic "segmentation fault" kind of error, after a bunch of "nan" results from integration. The very same code on the older pc was working just fine, so I guess it may be due to architecture in some way.
I found people suggesting to increase nstart and nincrease parameters of the used integrator by an order of magnitude or so, but nothing changes.
I'm using a brew-installed gcc version of g++-12 as mentioned, running on macOS Monterey version 12.3
Thanks everyone!
Edit 1: I'm adding the reduced code as well as the error message.
#include <stdlib.h>
#include <stdexcept>
#include <iostream>
#include <stdio.h>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm> // std::min
#include <math.h>
#include <cmath>
#include <memory>
#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions/bessel.hpp>
#include "cuba.h"
#include "gsl/gsl_rng.h" // scan
using boost::multiprecision::float128;
// ----------------------------------------------------- Physical constants
double eps2, qf, qD, mf, delta;
double T,sminima,spminima,saminima;
double TCB,Tfo;
double ma,mA,mAY,mZhatY,mAL,mZhatL;
double gfLAY,gfLZY,guLAY,guLZY,gdLAY,gdLZY,gfRAY,gfRZY,guRAY,guRZY,gdRAY,gdRZY,gnuLAY,gnuLZY,gXAY,gXZY,eps2Y;
double gfLAL,gfLZL,guLAL,guLZL,gdLAL,gdLZL,gfRAL,gfRZL,guRAL,guRZL,gdRAL,gdRZL,gnuLAL,gnuLZL,gXAL,gXZL,eps2L;
#define mX 0.01
#define m mX
#define s0 2970
#define rhocr 1.054e-05
#define T0 2.32e-13 //2.7 Kelvin in GeV
#define Tfr (mX/10.) // freeze-out temperature, xfr = 10
#define TCMB T0*(1) //CMB formation
#define mnu 1.e-9 // neutrino mass
#define mqt 173.21
#define mqb 4.18
#define mqc 1.27
#define mqs 96.e-3
#define mqd 4.7e-3
#define mqu 2.2e-3
#define mpionC 139.57e-3
#define mpion0 134.98e-3
#define mtau 1.78
#define mmu 105.66e-3
#define me 0.51e-3
#define mZ 91.19
#define mW 80.38
#define mH 125.09
#define pi 3.1415927
#define MP 1.22e19
#define qe 0.303
#define gquark 12.
#define ggluon 2.
#define Lqcd 0.217
#define gpion 3.
#define gchargedlepton 4.
#define gneutrino 2.
#define gmassiveboson 3.
#define gmasslessboson 2.
#define gscalar 1.
#define cW 0.8815
#define sW 0.4721
#define thetaW 0.4917 //radiant
// step function
int StepF(double x) {
int step;
if (x > 0.) {step = 1.;}
else { step = 0.;}
return step;
}
// dof function
double gstar(double x, int i) {
/* function computing the 2 effective d.o.f
i=1: ge, i=2:gs
*/
double TnuoT, res;
if (x > me) {
TnuoT = 1.;
}
else {
if (i == 1) {TnuoT = pow(4./11,4./3);}
else if (i == 2) {TnuoT = 4./11;}
}
res = StepF(x-Lqcd)*( gmasslessboson + 8.*ggluon + 7./8.*gquark*( StepF(x-mqt) + StepF(x-mqb) + StepF(x-mqc) + StepF(x-mqs) + StepF(x-mqd) + StepF(x-mqu) ) + gscalar*(StepF(x-mH) ) + gmassiveboson*( StepF(x-mA) + StepF(x-mZ) + 2.*StepF(x-mW) ) + 7./8.*( gchargedlepton*( StepF(x-me) + StepF(x-mmu) + StepF(x-mtau) ) + 3.*gneutrino + gneutrino*StepF(x-mX) ) ) +
StepF(Lqcd-x)*( gmasslessboson + gmassiveboson*StepF(x-mA) + gpion*( 2.*StepF(x-mpionC) + StepF(x-mpion0)) + 7./8.*(gchargedlepton*( StepF(x-me) + StepF(x-mmu)) + 3.*gneutrino*TnuoT + gneutrino*StepF(x-mX) ) );
return res;
}
// bessel functions
template <class T1, class T2>
long double cyl_bessel_k(T1 v, T2 x){
long double result;
result = cyl_bessel_k(v, x);
return result;
}
double Power(double x, double y){
return pow(x,y);
}
double Sqrt(double x){
return sqrt(x);
}
// ----------------------------------------------------- Gamma_A' U(1)_em x U(1)_d
double GammaA(double massA) {
double tw = 0.;
double PSe = 0.;
if(massA>2.*me)
PSe = eps2*pow(qe*qf,2.)*(1.+2.*me*me/(massA*massA))*sqrt(1.-4.*me*me/(massA*massA));
else PSe = 0.;
double PSmu = 0.;
if(massA>2.*mmu)
PSe = eps2*pow(qe*qf,2.)*(1.+2.*mmu*mmu/(massA*massA))*sqrt(1.-4.*mmu*mmu/(massA*massA));
else PSmu = 0.;
double PStau = 0.;
if(massA>2.*mtau)
PStau = eps2*pow(qe*qf,2.)*(1.+2.*mtau*mtau/(massA*massA))*sqrt(1.-4.*mtau*mtau/(massA*massA));
else PStau = 0.;
double PSqu = 0.;
if(massA>2.*mqu)
PSqu = eps2*Power(qe*qf*2./3.,2)*(1.+2.*mqu*mqu/(massA*massA))*sqrt(1.-4.*mqu*mqu/(massA*massA));
else PSqu = 0.;
double PSqc = 0.;
if(massA>2.*mqc)
PSqc = eps2*Power(qe*qf*2./3.,2)*(1.+2.*mqc*mqc/(massA*massA))*sqrt(1.-4.*mqc*mqc/(massA*massA));
else PSqc = 0.;
double PSqt = 0.;
if(massA>2.*mqt)
PSqt = eps2*Power(qe*qf*2./3.,2)*(1.+2.*mqt*mqt/(massA*massA))*sqrt(1.-4.*mqt*mqt/(massA*massA));
else PSqt = 0.;
double PSqd = 0.;
if(massA>2.*mqd)
PSqd = eps2*Power(qe*qf*1./3.,2)*(1.+2.*mqd*mqd/(massA*massA))*sqrt(1.-4.*mqd*mqd/(massA*massA));
else PSqd = 0.;
double PSqs = 0.;
if(massA>2.*mqs)
PSqs = eps2*Power(qe*qf*1./3.,2)*(1.+2.*mqs*mqs/(massA*massA))*sqrt(1.-4.*mqs*mqs/(massA*massA));
else PSqs = 0.;
double PSqb = 0.;
if(massA>2.*mqb)
PSqb = eps2*Power(qe*qf*1./3.,2)*(1.+2.*mqb*mqb/(massA*massA))*sqrt(1.-4.*mqb*mqb/(massA*massA));
else PSqb = 0.;
double PSX = 0.;
if(massA>2.*mX)
PSX = qD*qD*(1.+2.*mX*mX/(massA*massA))*sqrt(1.-4.*mX*mX/(massA*massA));
else PSX = 0.;
tw = massA/4./pi*( PSe + PSmu + PStau + PSX + 3.*(PSqu + PSqc + PSqt + PSqd + PSqs + PSqb)) ;
return tw;
}
// ----------------------------------------------------- Integral XX -> ee (em x d)
static int IntegrandEXXee(const int *ndim, const double xx[],
const int *ncomp, double ff[], void *userdata)
{
sminima = 4.*m*m;
#define st1 xx[1] // x
#define Tt1 xx[0] // y
#define f1 ff[0] // integrand: factor of yield
#define Tmax1 Tfr
#define Tmin1 T0
#define smax1 1000
#define smin1 sminima
#define T1 (Tmin1*exp( Tt1*log(Tmax1/Tmin1) ))
#define JacT1 (Tmin1*log(Tmax1/Tmin1)*exp(Tt1*log(Tmax1/Tmin1)))
#define s1 (smin1*exp( st1*log(smax1/smin1) ))
#define JacS1 (smin1*log(smax1/smin1)*exp(st1*log(smax1/smin1)))
long double func1;
long double neqX = gchargedlepton*mX*mX*T1*boost::math::cyl_bessel_k(2, mX/T1)/(2.*pi*pi);
long double sigma_XXff = Power(qe*qf*qD,2)*eps2*(s1+2.*m*m)*(s1+2.*mf*mf)*Sqrt(1-4.*mf*mf/s1)/(12.*pi*s1*Sqrt(1-4.*m*m/s1)*(Power(s1-mA*mA,2)+mA*mA*GammaA(mA)*GammaA(mA)));
func1 = JacT1 * JacS1;
func1 = func1 * Sqrt(pi/45) * MP * 2. * Power(pi,2.) * gchargedlepton/ Power(2.*pi,6.);
func1 = func1 * gstar(T1,2) * T1 /(sqrt(gstar(T1,1)) * neqX * neqX);
func1 = func1 * (sqrt(s1) * boost::math::cyl_bessel_k(1, sqrt(s1)/T1) * (s1-4.*m*m) * sigma_XXff);
f1 = func1;
return 0;
}
// ----------------------------------------------------- Common parameters
#define ndim 2
#define ncomp 1
#define userdata NULL
#define epsrel 1.e-1
#define epsabs 0
#define flags 6
//#define VERBOSE 2
//#define LAST 4
#define seed 1
#define mineval 1000
#define maxeval 300000
#define statefile NULL
// ----------------------------------------------------- Vegas-specific parameters
#define nstart 10000
#define nincrease 5000
#define nbatch 1000
#define gridno 1
int main(int numb, char** array)
{
double xtest;
long long int neval;
int fail;
double integralEXXee[ncomp], errorEXXee[ncomp],probEXXee[ncomp];
double numbd;
int nregions;
#define resultXXee integralEXXee[0]
#define errorXXee errorEXXee[0]
qD = 1.;
qf = 1.;
mA = 1.e-1;
eps2 = 1.e-8;
double neqX = gchargedlepton*mX*mX*Tfr*boost::math::cyl_bessel_k(2, mX/Tfr)/(2.*pi*pi);
double stot = 2.*pi*pi/45.*gstar(Tfr,2)*Tfr*Tfr*Tfr;
llVegas(ndim, ncomp, IntegrandEXXee, userdata, 1 /* nvec */,
epsrel, epsabs, flags, seed, mineval, maxeval, nstart, nincrease,
nbatch, gridno, statefile, NULL,&neval, &fail, integralEXXee, errorEXXee, probEXXee);
}
error I get on m1:
Iteration 1: 10000 integrand evaluations so far
[1] nan +- 2.22056e-18 chisq nan (0 df)
zsh: segmentation fault ./draft
the same routine works just fine on x86-64
edit:
Regardless of past comment, I managed to understand the problem ins't related to Cuba libraries but I'm guessing something related to arm64 architecture itself: if I remove a Bessel function from integrand a solution is found, whilst keeping it gives segmentation fault. There's something different in the way precision is treated at this point
Here is the case. I want to substitue ComplexDouble type and Double type to ComplexFloat and Float type in one of my files depend on a variables' value.
An example here:
Original code:
Tensor& float_power_out(Tensor& result, const Tensor& base, const Tensor& exp) {
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type())) ?
at::kComplexDouble : at::kDouble;
TORCH_CHECK(result.scalar_type() == dtype,
"the output given to float_power has dtype ", result.scalar_type(),
" but the operation's result requires dtype ", dtype);
return at::pow_out(result, base.to(dtype), exp.to(dtype));
}
What I expect to do (This is wrong)
#ifdef __NO_DOUBLE__
#define at::kComplexDouble at::kComplexFloat
#define at::kDouble at::kFloat
#endif
Tensor& float_power_out(Tensor& result, const Tensor& base, const Tensor& exp) {
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type())) ?
at::kComplexDouble : at::kDouble;
TORCH_CHECK(result.scalar_type() == dtype,
"the output given to float_power has dtype ", result.scalar_type(),
" but the operation's result requires dtype ", dtype);
return at::pow_out(result, base.to(dtype), exp.to(dtype));
}
#ifdef __NO_DOUBLE__
#undef at::kComplexDouble
#undef at::kDouble
#endif
But using VSCode C++ Intellisense, it informs me that the usage is wrong. It tells me that in my code at::kComplexDouble that the global scope has no "kDouble". I think its due to that in my #define at::kComplexDouble at::kComplexFloat statement, the :: actually get separated out from at. But I don't know how to write the correct syntax, I tried to add some ## token concatenations, but not doing it right, I guess. So, how to do this?
My worst choice is do it like this if I ever need a substition
Tensor& float_power_out(Tensor& result, const Tensor& base, const Tensor& exp) {
#ifdef __NO_DOUBLE__
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type())) ?
at::kComplexFloat : at::kFloat;
#else
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type())) ?
at::kComplexDouble : at::kDouble;
#endif
TORCH_CHECK(result.scalar_type() == dtype,
"the output given to float_power has dtype ", result.scalar_type(),
" but the operation's result requires dtype ", dtype);
return at::pow_out(result, base.to(dtype), exp.to(dtype));
}
But there will be 20 occurances of at::kComplexDouble in my file.
Ok, I have also tried to use using statement to do the substitution, but C++ Intellisense kept telling me my usage is wrong, here is what I tried so far:
#ifdef __NO_DOUBLE__
// #define at##::##kComplexDouble at##::##kComplexFloat
// #define at##::##kDouble at##::##kFloat
// #define toComplexDouble toComplexFloat
// #define toDouble toFloat
using at::kComplexFloat = at::kComplexDouble;
using at::kFloat = at::kDouble;
#endif
Tensor& float_power_out(Tensor& result, const Tensor& base, const Tensor& exp) {
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type())) ?
at::kComplexDouble : at::kDouble;
TORCH_CHECK(result.scalar_type() == dtype,
"the output given to float_power has dtype ", result.scalar_type(),
" but the operation's result requires dtype ", dtype);
return at::pow_out(result, base.to(dtype), exp.to(dtype));
}
It kept telling me qualified name is not allowed, and c10::kComplexDouble is not a type name error.
Besides, I don't know how to limit the range of using satements, meaning I don't want at::kFloat to mean at::kDouble anymore after some blocks of code here.
Edited:
Thanks for the answer provided by #molbdnilo. Besides, I just find that there are also some functions I need to substitute to float versions. For example, function calling toComplexDouble() and toDouble(), I want it to actually call toComplexFloat() and toFloat() if I defined my __NO_DOUBLE__ macro. So, would it work if I write it like this:
#ifdef __NO_DOUBLE__
#define toComplexDouble toComplexFloat
#define toDouble toFloat
...
#ifdef __NO_DOUBLE__
#undef toComplexDouble
#undef toDouble
Is the #undef needed here?
Edit:
Now I just figured out how not to include the namespace operators :: in my macro define statements, here is my solution, I think I need minimal code changes comparing to using const auto solution. Is this use case of macros bad practice?
#ifdef __NO_DOUBLE__
#define kComplexDouble kComplexFloat
#define kDouble kFloat
#define toComplexDouble toComplexFloat
#define toDouble toFloat
#endif
Tensor& float_power_out(Tensor& result, const Tensor& base, const Tensor& exp) {
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type())) ?
at::kComplexDouble : at::kDouble;
TORCH_CHECK(result.scalar_type() == dtype,
"the output given to float_power has dtype ", result.scalar_type(),
" but the operation's result requires dtype ", dtype);
return at::pow_out(result, base.to(dtype), exp.to(dtype));
}
...
#ifdef __NO_DOUBLE__
#undef kComplexDouble
#undef kDouble
#undef toComplexDouble
#undef toDouble
#endif
You can't have :: in a macro name.
Don't use macros, use variables with the desired values.
#ifdef __NO_DOUBLE__
const auto atComplex = at::kComplexFloat
const auto atFloat = at::kFloat
#else
const auto atComplex = at::kComplexDouble
const auto atFloat = at::kDouble
#endif
Tensor& float_power_out(Tensor& result, const Tensor& base, const Tensor& exp) {
auto dtype = (at::isComplexType(base.scalar_type()) || at::isComplexType(exp.scalar_type()))
? atComplex : atFloat;
TORCH_CHECK(result.scalar_type() == dtype,
"the output given to float_power has dtype ", result.scalar_type(),
" but the operation's result requires dtype ", dtype);
return at::pow_out(result, base.to(dtype), exp.to(dtype));
}
You could do the same thing with macros,
#ifdef __NO_DOUBLE__
#define atComplex at::kComplexFloat
#define atFloat at::kFloat
#else
#define atComplex at::kComplexDouble
#define atFloat at::kDouble
#endif
but why use macros when you don't need them?
You can do similar aliasing with functions:
#ifdef __NO_DOUBLE__
type1 toAtComplex(type2 t) { return at::toComplexFloat(t); }
#else
type1 toAtComplex(type2 t) { return at::toComplexDouble(t); }
#endif
I am providing an example with display resolutions but the question is more general.
Let say we have following configurations: 640x480; 1024x768; 1600x900. If they are defined separately it would look something like:
std::string RESTR[] = { "640x480", "1024x768", "1600x900" };
struct Enum { enum ERes { _640x480, _1024x768, _1600x900 }; };
uint RES[][2] = { { 640, 480 }, { 1024, 768 }, { 1600, 900 } };
It is too error prone to maintain all of the lists. It should be given the following way (or at least something very similar):
Res( 640, 480 )
Res( 1024, 768 )
Res( 1600, 900 )
A Resolution class would seem to be a fine solution, it behaves as a string when needed and returns a value in other use cases. But it does not have the enums before running the application. In order to utilize resolution enums in development a compile time magic, preprocessor or template definition is required. How could it be resolved?
Is there a standard state-of-art approach for this kind of problem?
There are two different approaches to solve problems of the such kind using only C++ tools (both of them use preprocessor's macros):
The approach based on variadic macro (you can write your own code or use Boost.Preprocessor library macros).
The approach based on X-macro technique.
Second approach is good for you if you use C++03 or lower (first one is available if you use C++11 or higher or if your C++ compiler supports C99). Here is its description:
Create an include file without include guards (you may give it an extension different from your usual header file extension, e.g. inc) with the name Resolution and the following contents:
RESOLUTION( 640, 480 )
RESOLUTION( 1024, 768 )
RESOLUTION( 1600, 900 )
Define your arrays as follows:
#define TO_STRING_LITERAL_(S) #S
#define TO_STRING_LITERAL(S) TO_STRING_LITERAL_(S)
#define STRING_RESOLUTION_(X, Y) X ## x ## Y
#define STRING_RESOLUTION(X, Y) TO_STRING_LITERAL(STRING_RESOLUTION_(X, Y)),
#define ENUM_RESOLUTION(X, Y) _ ## X ## x ## Y,
#define INT_RESOLUTION(X, Y) { X , Y },
#define RESOLUTION(X, Y) STRING_RESOLUTION(X, Y)
std::string RESTR[] =
{
# include "Resolution.inc"
};
#undef RESOLUTION
#define RESOLUTION(X, Y) ENUM_RESOLUTION(X, Y)
struct Enum
{
enum ERes
{
# include "Resolution.inc"
};
};
#undef
#define RESOLUTION(X, Y) INT_RESOLUTION(X, Y)
uint RES[][2] =
{
# include "Resolution.inc"
};
#undef
Update: #rici suggests in comments an interesting simplification of the STRING_RESOLUTION macro:
#define STRING_RESOLUTION(X, Y) #X "x" #Y
It is possible because a series of string literals is recognized as a one literal by a C++ compiler: "string1" "string2" "string3" == "string1string2string3".
If you are not married to using an enum, you can use something along the lines of:
#define CONCAT2(A, B) A ## B
#define CONCAT(A, B) CONCAT2(A, B)
#define STR2(A) #A
#define STR(A) STR2(A)
#define DEFINE_RESOLUTION(ResClass, X, Y) \
struct ResClass { \
static const int val = CONCAT(0x, CONCAT(X, Y)); \
static char const* toString() \
{ \
return STR(CONCAT(X, CONCAT(x, Y))); \
} \
static int getX() { return (X); } \
static int getY() { return (Y); } \
};
DEFINE_RESOLUTION(Res1, 640, 480);
DEFINE_RESOLUTION(Res2, 1024, 768);
// Test the code
#include <iostream>
int getint()
{
return Res1::val;
// return Res2::val;
}
int main()
{
int v = getint();
switch (v)
{
case Res1::val:
std::cout << Res1::getX() << "\n";
std::cout << Res1::getY() << "\n";
std::cout << Res1::toString() << "\n";
break;
case Res2::val:
std::cout << Res2::getX() << "\n";
std::cout << Res2::getY() << "\n";
std::cout << Res2::toString() << "\n";
break;
default:
std::cout << "Got default\n";
}
return 0;
}
Output:
640
480
640x480
I have this code inside a function but I am not able to understand what it does.
....
#define ascend(i) do {\
int h = nodes[i].heavyindex;\
int p = nodes[i].heavypos;\
m##i = max(m##i + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));\
i = paths[h].parent;\
} while (0)
while (nodes[a].heavyindex != nodes[b].heavyindex) {
if (nodes[a].heavyindex > nodes[b].heavyindex) {
ascend(a);
} else {
ascend(b);
}
}
#undef ascend
...
The code of #define, I think, is:
#define ascend(i) do {\
int h = nodes[i].heavyindex;\
int p = nodes[i].heavypos;\
m##i = max(m##i + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));\
i = paths[h].parent;\
} while (0)
so the real code inside the function is only this:
while (nodes[a].heavyindex != nodes[b].heavyindex) {
if (nodes[a].heavyindex > nodes[b].heavyindex) {
ascend(a);
} else {
ascend(b);
}
}
1) It is right?
2) I want to move the code of the #define inside a function to better understand what it does, but how I translate the following line?
m##i = max(m##i + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));\
Yes.
As mentioned by Ben Voigt in the comments, ## is the token-pasting operator. So with #define f(i) m##i defined, f(a) will expand to ma, f(b) will expand to mb, etc.
Since that's only possible with the preprocessor, you have to think of something else to implement it as a function. Passing ma and mb by reference would be a good idea. It could look something like this:
ascend(T& mi) {
...
mi = max(mi + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));
...
}
Where T is the type of ma and mb. If they're of different types, you need to make it a function template.
I have included file JSONValue from simpleJSON, which is used for parsing the json string.
While compiling I am getting this error that 'wcsncasecmp' was not declared in this scope.
on this line. While searching more i ot that wcsncasecmp is a GNU-specific function, I am using windows, so can anyone help me out.
else if ((simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"true", 4) == 0) || (simplejson_wcsnlen(*data, 5) && wcsncasecmp(*data, L"false", 5) == 0))
{
bool value = wcsncasecmp(*data, L"true", 4) == 0;
(*data) += value ? 4 : 5;
return new JSONValue(value);
}
.
I'll be greatful for any help.
On windows there is _wcsnicmp that you can use.
More ref: _strnicmp, _wcsnicmp, _mbsnicmp, _strnicmp_l, _wcsnicmp_l, _mbsnicmp_l
Please define WIN32 macro in your source or in Visual Studio please add it to the project / Properties / C/C++ / Preprocessor definition.
#define WIN32
Internally it will define wcsncasecmp as _wcsnicmp like Rohan has already mentioned.
This is a known problem of SimpleJSON.
// Win32 incompatibilities
#if defined(WIN32) && !defined(__GNUC__)
#define wcsncasecmp _wcsnicmp
static inline bool isnan(double x) { return x != x; }
static inline bool isinf(double x) { return !isnan(x) && isnan(x - x); }
#endif