// integer math class
// note: sinus/cosinus/atan table are not stored in const array to be available everywhere with
// symbian. (cannot be defined a global array), so must be rebuild if array size changed
#include "HG/HighGear.h"
#include "imath.h"

#include <stdlib.h>

#ifndef NGI
#include <math.h>
#endif // NGI

#include "config.h"
#include "constants.h"
#include "devutil.h"
#include "fsqrt.h"
#include "vector.h"

// sinus table, used for cosinus too with cos(x) = sin(x + pi/4)
const int Lib3D::TSIN[ANGLE2PI] = 
{
  0, 50, 101, 151, 201, 251, 302, 352, 402, 452, 503, 553, 603, 653, 704, 754, 
  804, 854, 904, 955, 1005, 1055, 1105, 1155, 1205, 1255, 1306, 1356, 1406, 1456, 1506, 1556, 
  1606, 1656, 1706, 1756, 1806, 1856, 1906, 1956, 2006, 2055, 2105, 2155, 2205, 2255, 2305, 2354, 
  2404, 2454, 2503, 2553, 2603, 2652, 2702, 2752, 2801, 2851, 2900, 2949, 2999, 3048, 3098, 3147, 
  3196, 3246, 3295, 3344, 3393, 3442, 3492, 3541, 3590, 3639, 3688, 3737, 3786, 3835, 3883, 3932, 
  3981, 4030, 4078, 4127, 4176, 4224, 4273, 4321, 4370, 4418, 4467, 4515, 4563, 4612, 4660, 4708, 
  4756, 4804, 4852, 4900, 4948, 4996, 5044, 5092, 5139, 5187, 5235, 5282, 5330, 5377, 5425, 5472, 
  5520, 5567, 5614, 5661, 5708, 5756, 5803, 5850, 5897, 5943, 5990, 6037, 6084, 6130, 6177, 6223, 
  6270, 6316, 6363, 6409, 6455, 6501, 6547, 6593, 6639, 6685, 6731, 6777, 6823, 6868, 6914, 6960, 
  7005, 7050, 7096, 7141, 7186, 7231, 7276, 7321, 7366, 7411, 7456, 7501, 7545, 7590, 7635, 7679, 
  7723, 7768, 7812, 7856, 7900, 7944, 7988, 8032, 8076, 8119, 8163, 8207, 8250, 8293, 8337, 8380, 
  8423, 8466, 8509, 8552, 8595, 8638, 8680, 8723, 8765, 8808, 8850, 8892, 8935, 8977, 9019, 9061, 
  9102, 9144, 9186, 9227, 9269, 9310, 9352, 9393, 9434, 9475, 9516, 9557, 9598, 9638, 9679, 9720, 
  9760, 9800, 9841, 9881, 9921, 9961, 10001, 10040, 10080, 10120, 10159, 10198, 10238, 10277, 10316, 10355, 
  10394, 10433, 10471, 10510, 10549, 10587, 10625, 10663, 10702, 10740, 10778, 10815, 10853, 10891, 10928, 10966, 
  11003, 11040, 11077, 11114, 11151, 11188, 11224, 11261, 11297, 11334, 11370, 11406, 11442, 11478, 11514, 11550, 
  11585, 11621, 11656, 11691, 11727, 11762, 11797, 11831, 11866, 11901, 11935, 11970, 12004, 12038, 12072, 12106, 
  12140, 12173, 12207, 12240, 12274, 12307, 12340, 12373, 12406, 12439, 12472, 12504, 12537, 12569, 12601, 12633, 
  12665, 12697, 12729, 12760, 12792, 12823, 12854, 12885, 12916, 12947, 12978, 13008, 13039, 13069, 13100, 13130, 
  13160, 13190, 13219, 13249, 13279, 13308, 13337, 13366, 13395, 13424, 13453, 13482, 13510, 13538, 13567, 13595, 
  13623, 13651, 13678, 13706, 13733, 13761, 13788, 13815, 13842, 13869, 13896, 13922, 13949, 13975, 14001, 14027, 
  14053, 14079, 14104, 14130, 14155, 14181, 14206, 14231, 14256, 14280, 14305, 14329, 14354, 14378, 14402, 14426, 
  14449, 14473, 14497, 14520, 14543, 14566, 14589, 14612, 14635, 14657, 14680, 14702, 14724, 14746, 14768, 14789, 
  14811, 14832, 14854, 14875, 14896, 14917, 14937, 14958, 14978, 14999, 15019, 15039, 15059, 15078, 15098, 15118, 
  15137, 15156, 15175, 15194, 15213, 15231, 15250, 15268, 15286, 15304, 15322, 15340, 15357, 15375, 15392, 15409, 
  15426, 15443, 15460, 15476, 15493, 15509, 15525, 15541, 15557, 15573, 15588, 15604, 15619, 15634, 15649, 15664, 
  15679, 15693, 15707, 15722, 15736, 15750, 15763, 15777, 15791, 15804, 15817, 15830, 15843, 15856, 15868, 15881, 
  15893, 15905, 15917, 15929, 15941, 15952, 15964, 15975, 15986, 15997, 16008, 16018, 16029, 16039, 16049, 16059, 
  16069, 16079, 16088, 16098, 16107, 16116, 16125, 16134, 16143, 16151, 16160, 16168, 16176, 16184, 16192, 16199, 
  16207, 16214, 16221, 16228, 16235, 16242, 16248, 16255, 16261, 16267, 16273, 16279, 16284, 16290, 16295, 16300, 
  16305, 16310, 16315, 16319, 16324, 16328, 16332, 16336, 16340, 16343, 16347, 16350, 16353, 16356, 16359, 16362, 
  16364, 16367, 16369, 16371, 16373, 16375, 16376, 16378, 16379, 16380, 16381, 16382, 16383, 16383, 16384, 16384, 
  16384, 16384, 16384, 16383, 16383, 16382, 16381, 16380, 16379, 16378, 16376, 16375, 16373, 16371, 16369, 16367, 
  16364, 16362, 16359, 16356, 16353, 16350, 16347, 16343, 16340, 16336, 16332, 16328, 16324, 16319, 16315, 16310, 
  16305, 16300, 16295, 16290, 16284, 16279, 16273, 16267, 16261, 16255, 16248, 16242, 16235, 16228, 16221, 16214, 
  16207, 16199, 16192, 16184, 16176, 16168, 16160, 16151, 16143, 16134, 16125, 16116, 16107, 16098, 16088, 16079, 
  16069, 16059, 16049, 16039, 16029, 16018, 16008, 15997, 15986, 15975, 15964, 15952, 15941, 15929, 15917, 15905, 
  15893, 15881, 15868, 15856, 15843, 15830, 15817, 15804, 15791, 15777, 15763, 15750, 15736, 15722, 15707, 15693, 
  15679, 15664, 15649, 15634, 15619, 15604, 15588, 15573, 15557, 15541, 15525, 15509, 15493, 15476, 15460, 15443, 
  15426, 15409, 15392, 15375, 15357, 15340, 15322, 15304, 15286, 15268, 15250, 15231, 15213, 15194, 15175, 15156, 
  15137, 15118, 15098, 15078, 15059, 15039, 15019, 14999, 14978, 14958, 14937, 14917, 14896, 14875, 14854, 14832, 
  14811, 14789, 14768, 14746, 14724, 14702, 14680, 14657, 14635, 14612, 14589, 14566, 14543, 14520, 14497, 14473, 
  14449, 14426, 14402, 14378, 14354, 14329, 14305, 14280, 14256, 14231, 14206, 14181, 14155, 14130, 14104, 14079, 
  14053, 14027, 14001, 13975, 13949, 13922, 13896, 13869, 13842, 13815, 13788, 13761, 13733, 13706, 13678, 13651, 
  13623, 13595, 13567, 13538, 13510, 13482, 13453, 13424, 13395, 13366, 13337, 13308, 13279, 13249, 13219, 13190, 
  13160, 13130, 13100, 13069, 13039, 13008, 12978, 12947, 12916, 12885, 12854, 12823, 12792, 12760, 12729, 12697, 
  12665, 12633, 12601, 12569, 12536, 12504, 12472, 12439, 12406, 12373, 12340, 12307, 12274, 12240, 12207, 12173, 
  12140, 12106, 12072, 12038, 12004, 11970, 11935, 11901, 11866, 11831, 11797, 11762, 11727, 11691, 11656, 11621, 
  11585, 11550, 11514, 11478, 11442, 11406, 11370, 11334, 11297, 11261, 11224, 11188, 11151, 11114, 11077, 11040, 
  11003, 10966, 10928, 10891, 10853, 10815, 10778, 10740, 10702, 10663, 10625, 10587, 10549, 10510, 10471, 10433, 
  10394, 10355, 10316, 10277, 10238, 10198, 10159, 10120, 10080, 10040, 10001, 9961, 9921, 9881, 9840, 9800, 
  9760, 9720, 9679, 9638, 9598, 9557, 9516, 9475, 9434, 9393, 9352, 9310, 9269, 9227, 9186, 9144, 
  9102, 9061, 9019, 8977, 8935, 8892, 8850, 8808, 8765, 8723, 8680, 8638, 8595, 8552, 8509, 8466, 
  8423, 8380, 8337, 8293, 8250, 8207, 8163, 8119, 8076, 8032, 7988, 7944, 7900, 7856, 7812, 7768, 
  7723, 7679, 7635, 7590, 7545, 7501, 7456, 7411, 7366, 7321, 7276, 7231, 7186, 7141, 7096, 7050, 
  7005, 6960, 6914, 6868, 6823, 6777, 6731, 6685, 6639, 6593, 6547, 6501, 6455, 6409, 6363, 6316, 
  6270, 6223, 6177, 6130, 6084, 6037, 5990, 5943, 5897, 5850, 5803, 5756, 5708, 5661, 5614, 5567, 
  5520, 5472, 5425, 5377, 5330, 5282, 5235, 5187, 5139, 5092, 5044, 4996, 4948, 4900, 4852, 4804, 
  4756, 4708, 4660, 4612, 4563, 4515, 4467, 4418, 4370, 4321, 4273, 4224, 4176, 4127, 4078, 4030, 
  3981, 3932, 3883, 3835, 3786, 3737, 3688, 3639, 3590, 3541, 3492, 3442, 3393, 3344, 3295, 3246, 
  3196, 3147, 3098, 3048, 2999, 2949, 2900, 2851, 2801, 2751, 2702, 2652, 2603, 2553, 2503, 2454, 
  2404, 2354, 2305, 2255, 2205, 2155, 2105, 2055, 2006, 1956, 1906, 1856, 1806, 1756, 1706, 1656, 
  1606, 1556, 1506, 1456, 1406, 1356, 1306, 1255, 1205, 1155, 1105, 1055, 1005, 955, 904, 854, 
  804, 754, 703, 653, 603, 553, 503, 452, 402, 352, 302, 251, 201, 151, 101, 50, 
  0, -49, -100, -150, -200, -250, -301, -351, -401, -451, -502, -552, -602, -652, -703, -753, 
  -803, -853, -903, -954, -1004, -1054, -1104, -1154, -1204, -1254, -1305, -1355, -1405, -1455, -1505, -1555, 
  -1605, -1655, -1705, -1755, -1805, -1855, -1905, -1955, -2005, -2054, -2104, -2154, -2204, -2254, -2304, -2353, 
  -2403, -2453, -2502, -2552, -2602, -2651, -2701, -2751, -2800, -2850, -2899, -2948, -2998, -3047, -3097, -3146, 
  -3195, -3245, -3294, -3343, -3392, -3441, -3491, -3540, -3589, -3638, -3687, -3736, -3785, -3834, -3882, -3931, 
  -3980, -4029, -4077, -4126, -4175, -4223, -4272, -4320, -4369, -4417, -4466, -4514, -4562, -4611, -4659, -4707, 
  -4755, -4803, -4851, -4899, -4947, -4995, -5043, -5091, -5138, -5186, -5234, -5281, -5329, -5376, -5424, -5471, 
  -5519, -5566, -5613, -5660, -5707, -5755, -5802, -5849, -5896, -5942, -5989, -6036, -6083, -6129, -6176, -6222, 
  -6269, -6315, -6362, -6408, -6454, -6500, -6546, -6592, -6638, -6684, -6730, -6776, -6822, -6867, -6913, -6959, 
  -7004, -7049, -7095, -7140, -7185, -7230, -7275, -7321, -7365, -7410, -7455, -7500, -7544, -7589, -7634, -7678, 
  -7722, -7767, -7811, -7855, -7899, -7943, -7987, -8031, -8075, -8118, -8162, -8206, -8249, -8292, -8336, -8379, 
  -8422, -8465, -8508, -8551, -8594, -8637, -8679, -8722, -8764, -8807, -8849, -8891, -8934, -8976, -9018, -9060, 
  -9101, -9143, -9185, -9226, -9268, -9309, -9351, -9392, -9433, -9474, -9515, -9556, -9597, -9637, -9678, -9719, 
  -9759, -9799, -9840, -9880, -9920, -9960, -10000, -10039, -10079, -10119, -10158, -10197, -10237, -10276, -10315, -10354, 
  -10393, -10432, -10470, -10509, -10548, -10586, -10624, -10662, -10701, -10739, -10777, -10814, -10852, -10890, -10927, -10965, 
  -11002, -11039, -11076, -11113, -11150, -11187, -11223, -11260, -11296, -11333, -11369, -11405, -11441, -11477, -11513, -11549, 
  -11584, -11620, -11655, -11690, -11726, -11761, -11796, -11830, -11865, -11900, -11934, -11969, -12003, -12037, -12071, -12105, 
  -12139, -12172, -12206, -12239, -12273, -12306, -12339, -12372, -12405, -12438, -12471, -12503, -12536, -12568, -12600, -12632, 
  -12664, -12696, -12728, -12759, -12791, -12822, -12853, -12884, -12915, -12946, -12977, -13007, -13038, -13068, -13099, -13129, 
  -13159, -13189, -13218, -13248, -13278, -13307, -13336, -13365, -13394, -13423, -13452, -13481, -13509, -13537, -13566, -13594, 
  -13622, -13650, -13677, -13705, -13732, -13760, -13787, -13814, -13841, -13868, -13895, -13921, -13948, -13974, -14000, -14026, 
  -14052, -14078, -14103, -14129, -14154, -14180, -14205, -14230, -14255, -14279, -14304, -14328, -14353, -14377, -14401, -14425, 
  -14448, -14472, -14496, -14519, -14542, -14565, -14588, -14611, -14634, -14656, -14679, -14701, -14723, -14745, -14767, -14788, 
  -14810, -14831, -14853, -14874, -14895, -14916, -14936, -14957, -14977, -14998, -15018, -15038, -15058, -15077, -15097, -15117, 
  -15136, -15155, -15174, -15193, -15212, -15230, -15249, -15267, -15285, -15303, -15321, -15339, -15356, -15374, -15391, -15408, 
  -15425, -15442, -15459, -15475, -15492, -15508, -15524, -15540, -15556, -15572, -15587, -15603, -15618, -15633, -15648, -15663, 
  -15678, -15692, -15706, -15721, -15735, -15749, -15762, -15776, -15790, -15803, -15816, -15829, -15842, -15855, -15867, -15880, 
  -15892, -15904, -15916, -15928, -15940, -15951, -15963, -15974, -15985, -15996, -16007, -16017, -16028, -16038, -16048, -16058, 
  -16068, -16078, -16087, -16097, -16106, -16115, -16124, -16133, -16142, -16150, -16159, -16167, -16175, -16183, -16191, -16198, 
  -16206, -16213, -16220, -16227, -16234, -16241, -16247, -16254, -16260, -16266, -16272, -16278, -16283, -16289, -16294, -16299, 
  -16304, -16309, -16314, -16318, -16323, -16327, -16331, -16335, -16339, -16342, -16346, -16349, -16352, -16355, -16358, -16361, 
  -16363, -16366, -16368, -16370, -16372, -16374, -16375, -16377, -16378, -16379, -16380, -16381, -16382, -16382, -16383, -16383, 
  -16383, -16383, -16383, -16382, -16382, -16381, -16380, -16379, -16378, -16377, -16375, -16374, -16372, -16370, -16368, -16366, 
  -16363, -16361, -16358, -16355, -16352, -16349, -16346, -16342, -16339, -16335, -16331, -16327, -16323, -16318, -16314, -16309, 
  -16304, -16299, -16294, -16289, -16283, -16278, -16272, -16266, -16260, -16254, -16247, -16241, -16234, -16227, -16220, -16213, 
  -16206, -16198, -16191, -16183, -16175, -16167, -16159, -16150, -16142, -16133, -16124, -16115, -16106, -16097, -16087, -16078, 
  -16068, -16058, -16048, -16038, -16028, -16017, -16007, -15996, -15985, -15974, -15963, -15951, -15940, -15928, -15916, -15904, 
  -15892, -15880, -15867, -15855, -15842, -15829, -15816, -15803, -15790, -15776, -15762, -15749, -15735, -15721, -15706, -15692, 
  -15678, -15663, -15648, -15633, -15618, -15603, -15587, -15572, -15556, -15540, -15524, -15508, -15492, -15475, -15459, -15442, 
  -15425, -15408, -15391, -15374, -15356, -15339, -15321, -15303, -15285, -15267, -15249, -15230, -15212, -15193, -15174, -15155, 
  -15136, -15117, -15097, -15077, -15058, -15038, -15018, -14998, -14977, -14957, -14936, -14916, -14895, -14874, -14853, -14831, 
  -14810, -14788, -14767, -14745, -14723, -14701, -14679, -14656, -14634, -14611, -14588, -14565, -14542, -14519, -14496, -14472, 
  -14448, -14425, -14401, -14377, -14353, -14328, -14304, -14279, -14255, -14230, -14205, -14180, -14154, -14129, -14103, -14078, 
  -14052, -14026, -14000, -13974, -13948, -13921, -13895, -13868, -13841, -13814, -13787, -13760, -13732, -13705, -13677, -13650, 
  -13622, -13594, -13566, -13537, -13509, -13481, -13452, -13423, -13394, -13365, -13336, -13307, -13278, -13248, -13218, -13189, 
  -13159, -13129, -13099, -13068, -13038, -13007, -12977, -12946, -12915, -12884, -12853, -12822, -12791, -12759, -12728, -12696, 
  -12664, -12632, -12600, -12568, -12535, -12503, -12471, -12438, -12405, -12372, -12339, -12306, -12273, -12239, -12206, -12172, 
  -12139, -12105, -12071, -12037, -12003, -11969, -11934, -11900, -11865, -11830, -11796, -11761, -11726, -11690, -11655, -11620, 
  -11584, -11549, -11513, -11477, -11441, -11405, -11369, -11333, -11296, -11260, -11223, -11187, -11150, -11113, -11076, -11039, 
  -11002, -10965, -10927, -10890, -10852, -10814, -10777, -10739, -10701, -10662, -10624, -10586, -10548, -10509, -10470, -10432, 
  -10393, -10354, -10315, -10276, -10237, -10197, -10158, -10119, -10079, -10039, -10000, -9960, -9920, -9880, -9839, -9799, 
  -9759, -9719, -9678, -9637, -9597, -9556, -9515, -9474, -9433, -9392, -9351, -9309, -9268, -9226, -9185, -9143, 
  -9101, -9060, -9018, -8976, -8934, -8891, -8849, -8807, -8764, -8722, -8679, -8637, -8594, -8551, -8508, -8465, 
  -8422, -8379, -8336, -8292, -8249, -8206, -8162, -8118, -8075, -8031, -7987, -7943, -7899, -7855, -7811, -7767, 
  -7722, -7678, -7634, -7589, -7544, -7500, -7455, -7410, -7365, -7320, -7275, -7230, -7185, -7140, -7095, -7049, 
  -7004, -6959, -6913, -6867, -6822, -6776, -6730, -6684, -6638, -6592, -6546, -6500, -6454, -6408, -6362, -6315, 
  -6269, -6222, -6176, -6129, -6083, -6036, -5989, -5942, -5896, -5849, -5802, -5755, -5707, -5660, -5613, -5566, 
  -5519, -5471, -5424, -5376, -5329, -5281, -5234, -5186, -5138, -5091, -5043, -4995, -4947, -4899, -4851, -4803, 
  -4755, -4707, -4659, -4611, -4562, -4514, -4466, -4417, -4369, -4320, -4272, -4223, -4175, -4126, -4077, -4029, 
  -3980, -3931, -3882, -3834, -3785, -3736, -3687, -3638, -3589, -3540, -3491, -3441, -3392, -3343, -3294, -3245, 
  -3195, -3146, -3097, -3047, -2998, -2948, -2899, -2850, -2800, -2750, -2701, -2651, -2602, -2552, -2502, -2453, 
  -2403, -2353, -2304, -2254, -2204, -2154, -2104, -2054, -2005, -1955, -1905, -1855, -1805, -1755, -1705, -1655, 
  -1605, -1555, -1505, -1455, -1405, -1355, -1305, -1254, -1204, -1154, -1104, -1054, -1004, -954, -903, -853, 
  -803, -753, -702, -652, -602, -552, -502, -451, -401, -351, -301, -250, -200, -150, -100, -49, 
};

const unsigned char AtanTab[ATAN_SIZE + 1] =
{
  0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 
  10, 10, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 19, 
  20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 
  30, 31, 31, 32, 32, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 39, 
  40, 41, 41, 42, 43, 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 49, 
  50, 51, 51, 52, 53, 53, 54, 54, 55, 56, 56, 57, 57, 58, 59, 59, 
  60, 61, 61, 62, 62, 63, 64, 64, 65, 65, 66, 67, 67, 68, 68, 69, 
  70, 70, 71, 72, 72, 73, 73, 74, 75, 75, 76, 76, 77, 78, 78, 79, 
  79, 80, 81, 81, 82, 82, 83, 84, 84, 85, 85, 86, 87, 87, 88, 88, 
  89, 89, 90, 91, 91, 92, 92, 93, 94, 94, 95, 95, 96, 96, 97, 98, 
  98, 99, 99, 100, 101, 101, 102, 102, 103, 103, 104, 105, 105, 106, 106, 107, 
  107, 108, 109, 109, 110, 110, 111, 111, 112, 113, 113, 114, 114, 115, 115, 116, 
  116, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 123, 123, 124, 124, 125, 
  125, 126, 126, 127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 
  134, 134, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 
  142, 143, 143, 144, 144, 145, 145, 146, 147, 147, 148, 148, 149, 149, 150, 150, 
  151, 151, 152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 
  159, 159, 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, 
  167, 167, 167, 168, 168, 169, 169, 170, 170, 171, 171, 172, 172, 173, 173, 174, 
  174, 175, 175, 176, 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, 
  182, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 187, 188, 188, 
  189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 195, 195, 195, 
  196, 196, 197, 197, 198, 198, 198, 199, 199, 200, 200, 201, 201, 201, 202, 202, 
  203, 203, 203, 204, 204, 205, 205, 206, 206, 206, 207, 207, 208, 208, 208, 209, 
  209, 210, 210, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 214, 215, 215, 
  216, 216, 216, 217, 217, 218, 218, 218, 219, 219, 220, 220, 220, 221, 221, 222, 
  222, 222, 223, 223, 223, 224, 224, 225, 225, 225, 226, 226, 226, 227, 227, 228, 
  228, 228, 229, 229, 229, 230, 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 
  234, 234, 235, 235, 235, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 
  239, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 
  245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 
  250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, 255, 
  255
};

// inverse trigo
#define ATN_ADJUST 0                 // round value to adjust (0 to disable, 1 to enable)
int Atan2i(int x, int y)
{
  if (x == 0)
  {
    if (y>=0) 
      return ANGLE2PI/4;
    else
      return (ANGLE2PI*3)/4;
  }

  int Index;
  if (x>0)
  {
    if (y>=0)
    {
      if (x>=y)
      {
        Index = (y*ATAN_SIZE)/x;
        return AtanTab[Index] + ATN_ADJUST;
      }
      else
      {
        Index = (x*ATAN_SIZE)/y;
        return ((ANGLE2PI/4) - ATN_ADJUST) - AtanTab[Index];
      }
    }
    else
    {
      y = -y;
      if (x>=y)
      {
        Index = (y*ATAN_SIZE)/x;
        return (ANGLE2PI - ATN_ADJUST) - AtanTab[Index];
      }
      else
      {
        Index = (x*ATAN_SIZE)/y;
        return (((ANGLE2PI*3)/4) + ATN_ADJUST) + AtanTab[Index];
      }
    }
  }
  else
  {
    x = -x;
    if (y>=0)
    {
      if (x>=y)
      {
        Index = (y*ATAN_SIZE)/x;
        return ((ANGLE2PI/2) - ATN_ADJUST) - AtanTab[Index];
      }
      else
      {
        Index = (x*ATAN_SIZE)/y;
        return ((ANGLE2PI/4) + ATN_ADJUST) + AtanTab[Index];
      }
    }
    else
    {
      y = -y;
      if (x>=y)
      {
        Index = (y*ATAN_SIZE)/x;
        return ((ANGLE2PI/2) + ATN_ADJUST) + AtanTab[Index];
      }
      else
      {
        Index = (x*ATAN_SIZE)/y;
        return (((ANGLE2PI*3)/4) - ATN_ADJUST) - AtanTab[Index];
      }
    }
  }
}

#if 0
// debug code to check Atan2i function
void Lib3D::CheckAtan2i(void)
{
  int ErrCtr = 0;   // if delta error < +/-1
  int BugCtr = 0;   // if delta error > +/-1 -> bug
  for (int i=0; i<ANGLE2PI; i++)
  {
    int x = 3*COSINUS(i);
    int y = 3*SINUS(i);
    int a = Atan2i(x, y);
    if (a < i)
      ErrCtr++;
    if (a > i)
      ErrCtr++;
    if ((a < (i-1)) || (a > (i+1)))
      BugCtr++;     // place breakpoint here
    if (a < 0)
      ErrCtr++;
    if (a >= ANGLE2PI)
      ErrCtr++;
  }
  // round error = ErrCtr;
}
#endif


int Lib3D::GetYOrient(Vector4s const & Src, Vector4s const & Dest)
{
  return Atan2i(Dest.z - Src.z, Dest.x - Src.x);
}

int Lib3D::GetXOrient(Vector4s const & Src,Vector4s const & Dest)
{
    Vector4s distVector = Dest - Src;
    int nXZLength= Lib3D::FSqrt(distVector.x * distVector.x + distVector.z * distVector.z);
    return Atan2i(nXZLength, distVector.y);
}

int Lib3D::AngleDiff(int SrcAngle, int TargetAngle)
{
  int Delta = (TargetAngle - SrcAngle) & ANGLEMASK;
  if (Delta > (ANGLE2PI/2))
    Delta -= ANGLE2PI;
  return Delta;
}

// return B with (1 << B) == A
int Lib3D::Log2(int a)
{
  int b = 0;
  while ((1<<b) <= a)
    b++;
  return b;
}


// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
int Lib3D::GetFovFromXAngle(int in_nXAngle)
{
    in_nXAngle>>=1;
    A_ASSERT(0 < in_nXAngle && in_nXAngle < PGL_PI);
    // tan
    int nTan = (Lib3D::Sinus(in_nXAngle)<<COS_SIN_SHIFT)/Lib3D::Cosinus(in_nXAngle);
    return ((CHighGear::GetInstance()->m_dispX>>1)<<COS_SIN_SHIFT)/nTan;
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
int Lib3D::GetFovFromYAngle(int in_nYAngle)
{
    in_nYAngle>>=1;
    A_ASSERT(0 < in_nYAngle && in_nYAngle < PGL_PI);
    // tan
    int nTan = (Lib3D::Sinus(in_nYAngle)<<COS_SIN_SHIFT)/Lib3D::Cosinus(in_nYAngle);
	return ((CHighGear::GetInstance()->m_dispY>>1)<<COS_SIN_SHIFT)/nTan;
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
int Lib3D::GetXAngleFromFov(int in_nFov)
{
    return Atan2i(in_nFov, CHighGear::GetInstance()->m_dispX>>1)<<1;
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
int Lib3D::GetYAngleFromFov(int in_nFov)
{
    return Atan2i(in_nFov, CHighGear::GetInstance()->m_dispY>>1)<<1;
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
int Lib3D::PositiveQuadraticRoot12(int i_A, int i_B, int i_C)
{
	if (i_A == 0)
	{
		if (i_B == 0)
		{
			// constant case
			return -1;
		}
		// linear case
		return Quotient12(-i_C, i_B);
	}
	bool const negativeA = i_A < 0;
	int rootShift = 0;
	int const abcMax = Max(Abs(i_A), Max(Abs(i_B), Abs(i_C)));
	int a12 = Quotient12(i_A, abcMax);
	int b12 = Quotient12(i_B, abcMax);
	int c12 = Quotient12(i_C, abcMax);
	int const ac24 = a12 * c12;
	int const discriminant24 = b12 * b12 - 4 * ac24;
	if (discriminant24 < 0)
	{
		// no real root
		return -1;
	}
	int const root = Product12(FSqrt(discriminant24), abcMax);
	int const t = -i_B + (((ac24 < 0) != negativeA) ? root : -root);
	if ((t < 0) != negativeA)
	{
		// no positive root
		return -1;
	}
	return Quotient12(t, 2 * i_A);
}





//#if CHECK_MATH
#if defined (WIN32) && !defined(WINDOWS_MOBILE)

#include <limits.h>

volatile static bool _disable = false;

// ---------------------------------------------------------------------------
//	Used bu debug macros CHK_MULT and CHK_LIMITS; see config.h
// ---------------------------------------------------------------------------
void _Check_Int_Limit(double x)
{

	if(!_disable)
	{
		A_ASSERT(x <= double(INT_MAX) && x >= double(INT_MIN));
	}

}


void _Check_Short_Limit(double x)
{
	if(!_disable)
	{
		A_ASSERT(x <= double(SHRT_MAX) && x >= double(SHRT_MIN));
	}
}





void _Check_Precision(double fResult, int nResult, double fTolerancePercentage)
{
    double fError = fResult - nResult;
    if (fError < 0) fError = -fError;
    double fTolerance = fTolerancePercentage*fResult/100;
    if (fTolerance < 0) fTolerance = -fTolerance;
    A_ASSERT(int(fError) <= int(fTolerance)); // always tolerate decimal error
}

#endif //#if CHECK_MATH