core/logic/smn_float.cpp
author David Anderson <dvander@alliedmods.net>
Wed Apr 23 10:18:56 2014 -0700 (2014-04-23)
changeset 4331 da66b9161507
parent 4329 5ac935cb029a
permissions -rw-r--r--
Fix typo pointed out by Nephrite (bug 6107, comment #7).
dvander@2726
     1
/**
dvander@2833
     2
 * vim: set ts=4 sw=4 tw=99 :
dvander@2726
     3
 * =============================================================================
dvander@2726
     4
 * SourceMod
dvander@2726
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@2726
     6
 * =============================================================================
dvander@2726
     7
 *
dvander@2726
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@2726
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2726
    10
 * Free Software Foundation.
dvander@2726
    11
 * 
dvander@2726
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2726
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2726
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2726
    15
 * details.
dvander@2726
    16
 *
dvander@2726
    17
 * You should have received a copy of the GNU General Public License along with
dvander@2726
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2726
    19
 *
dvander@2726
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2726
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2726
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2726
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2726
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2726
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@2726
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2726
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@2726
    28
 *
dvander@2726
    29
 * Version: $Id$
dvander@2726
    30
 */
dvander@2726
    31
dvander@2726
    32
#include <math.h>
dvander@2726
    33
#include <string.h>
dvander@2726
    34
#include <stdlib.h>
dvander@2726
    35
#include "common_logic.h"
dvander@2833
    36
#include "MersenneTwister.h"
dvander@2833
    37
#include <IPluginSys.h>
dvander@4329
    38
#include <am-utility.h>
dvander@2726
    39
dvander@2726
    40
/****************************************
dvander@2726
    41
*                                       *
dvander@2726
    42
* FLOATING POINT NATIVE IMPLEMENTATIONS *
dvander@2726
    43
*                                       *
dvander@2726
    44
****************************************/
dvander@2726
    45
dvander@2726
    46
dvander@2726
    47
static cell_t sm_float(IPluginContext *pCtx, const cell_t *params)
dvander@2726
    48
{
dvander@2726
    49
	float val = static_cast<float>(params[1]);
dvander@2726
    50
dvander@2726
    51
	return sp_ftoc(val);
dvander@2726
    52
}
dvander@2726
    53
dvander@2726
    54
static cell_t sm_FloatAbs(IPluginContext *pCtx, const cell_t *params)
dvander@2726
    55
{
dvander@2726
    56
	float val = sp_ctof(params[1]);
dvander@2726
    57
	val = (val >= 0.0f) ? val : -val;
dvander@2726
    58
dvander@2726
    59
	return sp_ftoc(val);
dvander@2726
    60
}
dvander@2726
    61
dvander@2726
    62
static cell_t sm_FloatAdd(IPluginContext *pCtx, const cell_t *params)
dvander@2726
    63
{
dvander@2726
    64
	float val = sp_ctof(params[1]) + sp_ctof(params[2]);
dvander@2726
    65
dvander@2726
    66
	return sp_ftoc(val);
dvander@2726
    67
}
dvander@2726
    68
dvander@2726
    69
static cell_t sm_FloatSub(IPluginContext *pCtx, const cell_t *params)
dvander@2726
    70
{
dvander@2726
    71
	float val = sp_ctof(params[1]) - sp_ctof(params[2]);
dvander@2726
    72
dvander@2726
    73
	return sp_ftoc(val);
dvander@2726
    74
}
dvander@2726
    75
dvander@2726
    76
static cell_t sm_FloatMul(IPluginContext *pCtx, const cell_t *params)
dvander@2726
    77
{
dvander@2726
    78
	float val = sp_ctof(params[1]) * sp_ctof(params[2]);
dvander@2726
    79
dvander@2726
    80
	return sp_ftoc(val);
dvander@2726
    81
}
dvander@2726
    82
dvander@2726
    83
static cell_t sm_FloatDiv(IPluginContext *pCtx, const cell_t *params)
dvander@2726
    84
{
dvander@2726
    85
	float val = sp_ctof(params[1]) / sp_ctof(params[2]);
dvander@2726
    86
dvander@2726
    87
	return sp_ftoc(val);
dvander@2726
    88
}
dvander@2726
    89
dvander@4327
    90
static cell_t sm_FloatGt(IPluginContext *pCtx, const cell_t *params)
dvander@4327
    91
{
dvander@4327
    92
	return !!(sp_ctof(params[1]) > sp_ctof(params[2]));
dvander@4327
    93
}
dvander@4327
    94
dvander@4327
    95
static cell_t sm_FloatGe(IPluginContext *pCtx, const cell_t *params)
dvander@4327
    96
{
dvander@4327
    97
	return !!(sp_ctof(params[1]) >= sp_ctof(params[2]));
dvander@4327
    98
}
dvander@4327
    99
dvander@4327
   100
static cell_t sm_FloatLt(IPluginContext *pCtx, const cell_t *params)
dvander@4327
   101
{
dvander@4327
   102
	return !!(sp_ctof(params[1]) < sp_ctof(params[2]));
dvander@4327
   103
}
dvander@4327
   104
dvander@4327
   105
static cell_t sm_FloatLe(IPluginContext *pCtx, const cell_t *params)
dvander@4327
   106
{
dvander@4327
   107
	return !!(sp_ctof(params[1]) <= sp_ctof(params[2]));
dvander@4327
   108
}
dvander@4327
   109
dvander@4327
   110
static cell_t sm_FloatEq(IPluginContext *pCtx, const cell_t *params)
dvander@4327
   111
{
dvander@4327
   112
	return !!(sp_ctof(params[1]) == sp_ctof(params[2]));
dvander@4327
   113
}
dvander@4327
   114
dvander@4327
   115
static cell_t sm_FloatNe(IPluginContext *pCtx, const cell_t *params)
dvander@4327
   116
{
dvander@4327
   117
	return !!(sp_ctof(params[1]) != sp_ctof(params[2]));
dvander@4327
   118
}
dvander@4327
   119
dvander@4327
   120
static cell_t sm_FloatNot(IPluginContext *pCtx, const cell_t *params)
dvander@4327
   121
{
dvander@4327
   122
	float val = sp_ctof(params[1]);
dvander@4329
   123
	if (ke::IsNaN(val))
dvander@4327
   124
		return 1;
dvander@4327
   125
	return val ? 0 : 1;
dvander@4327
   126
}
dvander@4327
   127
dvander@2726
   128
static cell_t sm_FloatCompare(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   129
{
dvander@2726
   130
	float val1 = sp_ctof(params[1]);
dvander@2726
   131
	float val2 = sp_ctof(params[2]);
dvander@2726
   132
dvander@2726
   133
	if (val1 > val2)
dvander@2726
   134
	{
dvander@2726
   135
		return 1;
dvander@2726
   136
	} else if (val1 < val2) {
dvander@2726
   137
		return -1;
dvander@2726
   138
	}
dvander@2726
   139
dvander@2726
   140
	return 0;
dvander@2726
   141
}
dvander@2726
   142
dvander@2726
   143
static cell_t sm_Logarithm(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   144
{
dvander@2726
   145
	float val = sp_ctof(params[1]);
dvander@2726
   146
	float base = sp_ctof(params[2]);
dvander@2726
   147
dvander@2726
   148
	if ((val <= 0.0f) || (base <= 0.0f))
dvander@2726
   149
	{
dvander@2726
   150
		return pCtx->ThrowNativeError("Cannot evaluate the logarithm of zero or a negative number (val:%f base:%f)", val, base);
dvander@2726
   151
	}
dvander@2726
   152
	if (base == 10.0f)
dvander@2726
   153
	{
dvander@2726
   154
		val = log10(val);
dvander@2726
   155
	} else {
dvander@2726
   156
		val = log(val) / log(base);
dvander@2726
   157
	}
dvander@2726
   158
dvander@2726
   159
	return sp_ftoc(val);
dvander@2726
   160
}
dvander@2726
   161
dvander@2726
   162
static cell_t sm_Exponential(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   163
{
dvander@2726
   164
	float val = sp_ctof(params[1]);
dvander@2726
   165
dvander@2726
   166
	return sp_ftoc(exp(val));
dvander@2726
   167
}
dvander@2726
   168
dvander@2726
   169
static cell_t sm_Pow(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   170
{
dvander@2726
   171
	float base = sp_ctof(params[1]);
dvander@2726
   172
	float exponent = sp_ctof(params[2]);
dvander@2726
   173
dvander@2726
   174
	return sp_ftoc(pow(base, exponent));
dvander@2726
   175
}
dvander@2726
   176
dvander@2726
   177
static cell_t sm_SquareRoot(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   178
{
dvander@2726
   179
	float val = sp_ctof(params[1]);
dvander@2726
   180
dvander@2726
   181
	if (val < 0.0f)
dvander@2726
   182
	{
dvander@2726
   183
		return pCtx->ThrowNativeError("Cannot evaluate the square root of a negative number (val:%f)", val);
dvander@2726
   184
	}
dvander@2726
   185
dvander@2726
   186
	return sp_ftoc(sqrt(val));
dvander@2726
   187
}
dvander@2726
   188
dvander@2726
   189
static cell_t sm_RoundToNearest(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   190
{
dvander@2726
   191
	float val = sp_ctof(params[1]);
dvander@2726
   192
	val = (float)floor(val + 0.5f);
dvander@2726
   193
dvander@2726
   194
	return static_cast<int>(val);
dvander@2726
   195
}
dvander@2726
   196
dvander@2726
   197
static cell_t sm_RoundToFloor(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   198
{
dvander@2726
   199
	float val = sp_ctof(params[1]);
dvander@2726
   200
	val = floor(val);
dvander@2726
   201
dvander@2726
   202
	return static_cast<int>(val);
dvander@2726
   203
}
dvander@2726
   204
dvander@2726
   205
static cell_t sm_RoundToCeil(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   206
{
dvander@2726
   207
	float val = sp_ctof(params[1]);
dvander@2726
   208
	val = ceil(val);
dvander@2726
   209
dvander@2726
   210
	return static_cast<int>(val);
dvander@2726
   211
}
dvander@2726
   212
dvander@2726
   213
static cell_t sm_RoundToZero(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   214
{
dvander@2726
   215
	float val = sp_ctof(params[1]);
dvander@2726
   216
	if (val >= 0.0f)
dvander@2726
   217
	{
dvander@2726
   218
		val = floor(val);
dvander@2726
   219
	} else {
dvander@2726
   220
		val = ceil(val);
dvander@2726
   221
	}
dvander@2726
   222
dvander@2726
   223
	return static_cast<int>(val);
dvander@2726
   224
}
dvander@2726
   225
dvander@2726
   226
static cell_t sm_FloatFraction(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   227
{
dvander@2726
   228
	float val = sp_ctof(params[1]);
dvander@2726
   229
	val = val - floor(val);
dvander@2726
   230
dvander@2726
   231
	return sp_ftoc(val);
dvander@2726
   232
}
dvander@2726
   233
dvander@2726
   234
static cell_t sm_Sine(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   235
{
dvander@2726
   236
	float val = sp_ctof(params[1]);
dvander@2726
   237
	val = sin(val);
dvander@2726
   238
dvander@2726
   239
	return sp_ftoc(val);
dvander@2726
   240
}
dvander@2726
   241
dvander@2726
   242
static cell_t sm_Cosine(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   243
{
dvander@2726
   244
	float val = sp_ctof(params[1]);
dvander@2726
   245
	val = cos(val);
dvander@2726
   246
dvander@2726
   247
	return sp_ftoc(val);
dvander@2726
   248
}
dvander@2726
   249
dvander@2726
   250
static cell_t sm_Tangent(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   251
{
dvander@2726
   252
	float val = sp_ctof(params[1]);
dvander@2726
   253
	val = tan(val);
dvander@2726
   254
dvander@2726
   255
	return sp_ftoc(val);
dvander@2726
   256
}
dvander@2726
   257
dvander@2726
   258
static cell_t sm_ArcSine(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   259
{
dvander@2726
   260
	float val = sp_ctof(params[1]);
dvander@2726
   261
	val = asin(val);
dvander@2726
   262
dvander@2726
   263
	return sp_ftoc(val);
dvander@2726
   264
}
dvander@2726
   265
dvander@2726
   266
static cell_t sm_ArcCosine(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   267
{
dvander@2726
   268
	float val = sp_ctof(params[1]);
dvander@2726
   269
	val = acos(val);
dvander@2726
   270
dvander@2726
   271
	return sp_ftoc(val);
dvander@2726
   272
}
dvander@2726
   273
dvander@2726
   274
static cell_t sm_ArcTangent(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   275
{
dvander@2726
   276
	float val = sp_ctof(params[1]);
dvander@2726
   277
	val = atan(val);
dvander@2726
   278
dvander@2726
   279
	return sp_ftoc(val);
dvander@2726
   280
}
dvander@2726
   281
dvander@2726
   282
static cell_t sm_ArcTangent2(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   283
{
dvander@2726
   284
	float val1 = sp_ctof(params[1]);
dvander@2726
   285
	float val2 = sp_ctof(params[2]);
dvander@2726
   286
	val1 = atan2(val1, val2);
dvander@2726
   287
dvander@2726
   288
	return sp_ftoc(val1);
dvander@2726
   289
}
dvander@2726
   290
dvander@2726
   291
#if 0
dvander@2726
   292
static cell_t sm_FloatRound(IPluginContext *pCtx, const cell_t *params)
dvander@2726
   293
{
dvander@2726
   294
	float val = sp_ctof(params[1]);
dvander@2726
   295
dvander@2726
   296
	switch (params[2])
dvander@2726
   297
	{
dvander@2726
   298
	case 1:
dvander@2726
   299
		{
dvander@2726
   300
			val = floor(val);
dvander@2726
   301
			break;
dvander@2726
   302
		}
dvander@2726
   303
	case 2:
dvander@2726
   304
		{
dvander@2726
   305
			val = ceil(val);
dvander@2726
   306
			break;
dvander@2726
   307
		}
dvander@2726
   308
	case 3:
dvander@2726
   309
		{
dvander@2726
   310
			if (val >= 0.0f)
dvander@2726
   311
			{
dvander@2726
   312
				val = floor(val);
dvander@2726
   313
			} else {
dvander@2726
   314
				val = ceil(val);
dvander@2726
   315
			}
dvander@2726
   316
			break;
dvander@2726
   317
		}
dvander@2726
   318
	default:
dvander@2726
   319
		{
dvander@2726
   320
			val = (float)floor(val + 0.5f);
dvander@2726
   321
			break;
dvander@2726
   322
		}
dvander@2726
   323
	}
dvander@2726
   324
dvander@2726
   325
	return static_cast<int>(val);
dvander@2726
   326
}
dvander@2726
   327
#endif
dvander@2726
   328
dvander@2833
   329
class RandomHelpers :
dvander@2833
   330
	public SMGlobalClass,
dvander@2833
   331
	public IPluginsListener
dvander@2833
   332
{
dvander@2833
   333
public:
dvander@2833
   334
	void OnSourceModAllInitialized()
dvander@2833
   335
	{
dvander@2833
   336
		pluginsys->AddPluginsListener(this);
dvander@2833
   337
	}
dvander@2833
   338
dvander@2833
   339
	void OnSourceModShutdown()
dvander@2833
   340
	{
dvander@2833
   341
		pluginsys->RemovePluginsListener(this);
dvander@2833
   342
	}
dvander@2833
   343
dvander@2833
   344
	void OnPluginDestroyed(IPlugin *plugin)
dvander@2833
   345
	{
dvander@2833
   346
		MTRand *mtrand;
dvander@2833
   347
		if (plugin->GetProperty("core.logic.mtrand", (void**)&mtrand, true))
dvander@2833
   348
		{
dvander@2833
   349
			delete mtrand;
dvander@2833
   350
		}
dvander@2833
   351
	}
dvander@2833
   352
	
dvander@2833
   353
	MTRand *RandObjForPlugin(IPluginContext *ctx)
dvander@2833
   354
	{
dvander@2833
   355
		IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
dvander@2833
   356
		MTRand *mtrand;	
dvander@2833
   357
		if (!plugin->GetProperty("core.logic.mtrand", (void**)&mtrand))
dvander@2833
   358
		{
dvander@2833
   359
			mtrand = new MTRand();
dvander@2833
   360
			plugin->SetProperty("core.logic.mtrand", mtrand);
dvander@2833
   361
		}
dvander@2833
   362
		return mtrand;
dvander@2833
   363
	}
dvander@2833
   364
} s_RandHelpers;
dvander@2833
   365
dvander@2833
   366
static cell_t GetURandomInt(IPluginContext *ctx, const cell_t *params)
dvander@2833
   367
{
dvander@2833
   368
	MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
dvander@2833
   369
	/* Note the sign bit must be stripped off because cell_t is signed,
dvander@2833
   370
	 * and this guarantees a range of [0,max_int]
dvander@2833
   371
	 */
dvander@2833
   372
	return randobj->randInt() & 0x7FFFFFFF;
dvander@2833
   373
}
dvander@2833
   374
dvander@2833
   375
static cell_t GetURandomFloat(IPluginContext *ctx, const cell_t *params)
dvander@2833
   376
{
dvander@2833
   377
	MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
dvander@2833
   378
	return sp_ftoc((float)randobj->rand());
dvander@2833
   379
}
dvander@2833
   380
dvander@2833
   381
static cell_t SetURandomSeed(IPluginContext *ctx, const cell_t *params)
dvander@2833
   382
{
dvander@2833
   383
	MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
dvander@2833
   384
	cell_t *addr;
dvander@2833
   385
	ctx->LocalToPhysAddr(params[1], &addr);
dvander@2833
   386
	/* We're 32-bit only. */
dvander@2833
   387
	randobj->seed((MTRand::uint32*)addr, params[2]);
dvander@2833
   388
	return 1;
dvander@2833
   389
}
dvander@2833
   390
dvander@2726
   391
REGISTER_NATIVES(floatnatives)
dvander@2726
   392
{
dvander@2726
   393
	{"float",			sm_float},
dvander@2726
   394
	{"FloatMul",		sm_FloatMul},
dvander@2726
   395
	{"FloatDiv",		sm_FloatDiv},
dvander@2726
   396
	{"FloatAdd",		sm_FloatAdd},
dvander@2726
   397
	{"FloatSub",		sm_FloatSub},
dvander@2726
   398
	{"FloatFraction",	sm_FloatFraction},
dvander@2726
   399
	{"RoundToZero",		sm_RoundToZero},
dvander@2726
   400
	{"RoundToCeil",		sm_RoundToCeil},
dvander@2726
   401
	{"RoundToFloor",	sm_RoundToFloor},
dvander@2726
   402
	{"RoundToNearest",	sm_RoundToNearest},
dvander@4327
   403
	{"__FLOAT_GT__",	sm_FloatGt},
dvander@4327
   404
	{"__FLOAT_GE__",	sm_FloatGe},
dvander@4331
   405
	{"__FLOAT_LT__",	sm_FloatLt},
dvander@4327
   406
	{"__FLOAT_LE__",	sm_FloatLe},
dvander@4327
   407
	{"__FLOAT_EQ__",	sm_FloatEq},
dvander@4327
   408
	{"__FLOAT_NE__",	sm_FloatNe},
dvander@4327
   409
	{"__FLOAT_NOT__",	sm_FloatNot},
dvander@2726
   410
	{"FloatCompare",	sm_FloatCompare},
dvander@2726
   411
	{"SquareRoot",		sm_SquareRoot},
dvander@2726
   412
	{"Pow",				sm_Pow},
dvander@2726
   413
	{"Exponential",		sm_Exponential},
dvander@2726
   414
	{"Logarithm",		sm_Logarithm},
dvander@2726
   415
	{"Sine",			sm_Sine},
dvander@2726
   416
	{"Cosine",			sm_Cosine},
dvander@2726
   417
	{"Tangent",			sm_Tangent},
dvander@2726
   418
	{"FloatAbs",		sm_FloatAbs},
dvander@2726
   419
	{"ArcTangent",		sm_ArcTangent},
dvander@2726
   420
	{"ArcCosine",		sm_ArcCosine},
dvander@2726
   421
	{"ArcSine",			sm_ArcSine},
dvander@2726
   422
	{"ArcTangent2",		sm_ArcTangent2},
dvander@2833
   423
	{"GetURandomInt",	GetURandomInt},
dvander@2833
   424
	{"GetURandomFloat",	GetURandomFloat},
dvander@2833
   425
	{"SetURandomSeed",	SetURandomSeed},
dvander@2726
   426
	{NULL,				NULL}
dvander@2726
   427
};
dvander@2833
   428